Пример #1
0
    def __init__(self, *args, **kwargs):
        super(ButtonGroupFieldWidget, self).__init__(*args, **kwargs)

        self._value = ''
        self._buttons = dict()

        items = self.data().get('items')

        widget = QFrame(self)
        layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        widget.setLayout(layout)

        index = 0
        for item in items:
            index += 1
            button = buttons.BaseButton(item, parent=self)
            button.setCheckable(True)
            button_callback = partial(self.set_value, item)
            button.clicked.connect(button_callback)
            self._buttons[item] = button
            if index == 1:
                button.setProperty('first', True)
            if index == len(items):
                button.setProperty('last', True)

        self.set_widget(widget)
Пример #2
0
    def createWidget(self, menu):
        """
        Overrides base QWidgetAction createWidget function
        :param menu: QMenu
        """

        widget = QFrame(self.parent())
        widget.setObjectName('filterByAction')
        title = self._name
        label = checkbox.BaseCheckBox(parent=widget)
        label.setText(title)
        label.setAttribute(Qt.WA_TransparentForMouseEvents)
        label.toggled.connect(self._on_triggered)
        label.setStyleSheet("""
        #QCheckBox::indicator:checked {
            image: url(none.png)
        }
        QCheckBox::indicator:unchecked {
            image: url(none.png)
        }
        """)
        action_layout = layouts.HorizontalLayout(margins=(0, 0, 0, 0))
        action_layout.addWidget(label, stretch=1)
        widget.setLayout(action_layout)

        return widget
Пример #3
0
    def createWidget(self, menu):
        """
        Overrides base QWidgetAction createWidget function
        :param menu: QMenu
        :return: QWidget
        """

        widget = QFrame(self.parent())
        widget.setObjectName('filterByAction')
        facet = self._facet
        name = facet.get('name', '')
        count = str(facet.get('count', 0))
        title = name.replace('.', '').title()
        cbx = checkbox.BaseCheckBox(parent=widget)
        cbx.setAttribute(Qt.WA_TransparentForMouseEvents)
        cbx.setText(title)
        cbx.installEventFilter(self)
        cbx.setChecked(self._checked)
        label2 = label.BaseLabel(parent=widget)
        label2.setObjectName('actionCounter')
        label2.setText(count)
        layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        layout.addWidget(cbx, stretch=1)
        layout.addWidget(label2)
        widget.setLayout(layout)

        cbx.toggled.connect(self._on_triggered)

        return widget
Пример #4
0
    def createWidget(self, menu):
        widget = QFrame(menu)
        widget.setObjectName('iconPickerAction')
        action_layout = layouts.HorizontalLayout(margins=(0, 0, 0, 0))
        action_layout.addWidget(self.picker(), stretch=1)
        widget.setLayout(action_layout)

        return widget
Пример #5
0
    def ui(self):
        super(BaseSaveWidget, self).ui()

        title_layout = layouts.HorizontalLayout()
        title_layout.setContentsMargins(2, 2, 0, 0)
        title_layout.setSpacing(2)
        self._icon_lbl = QLabel()
        self._icon_lbl.setMaximumSize(QSize(14, 14))
        self._icon_lbl.setMinimumSize(QSize(14, 14))
        self._icon_lbl.setScaledContents(True)
        self._title_lbl = QLabel()
        title_layout.addWidget(self._icon_lbl)
        title_layout.addWidget(self._title_lbl)

        self._folder_widget = directory.SelectFolder('Folder',
                                                     use_app_browser=True)

        buttons_layout = layouts.HorizontalLayout()
        buttons_layout.setContentsMargins(4, 4, 4, 4)
        buttons_layout.setSpacing(4)
        buttons_frame = QFrame()
        buttons_frame.setFrameShape(QFrame.NoFrame)
        buttons_frame.setFrameShadow(QFrame.Plain)
        buttons_frame.setLayout(buttons_layout)
        buttons_layout.addStretch()
        self.save_btn = buttons.BaseButton('Save')
        self.cancel_btn = buttons.BaseButton('Cancel')
        buttons_layout.addWidget(self.save_btn, parent=self)
        buttons_layout.addWidget(self.cancel_btn, parent=self)
        buttons_layout.addStretch()

        self._options_layout = layouts.VerticalLayout()
        self._options_layout.setContentsMargins(0, 0, 0, 0)
        self._options_layout.setSpacing(2)
        self._options_frame = QFrame()
        self._options_frame.setFrameShape(QFrame.NoFrame)
        self._options_frame.setFrameShadow(QFrame.Plain)
        self._options_frame.setLineWidth(0)
        self._options_frame.setLayout(self._options_layout)

        self._extra_layout = layouts.VerticalLayout()
        self._extra_layout.setContentsMargins(0, 0, 0, 0)
        self._extra_layout.setSpacing(2)

        self.main_layout.addLayout(title_layout)
        self.main_layout.addWidget(self._folder_widget)
        self._extra_layout.addWidget(self._options_frame)
        self.main_layout.addWidget(dividers.Divider())
        self.main_layout.addLayout(self._extra_layout)
        self.main_layout.addWidget(dividers.Divider())
        self.main_layout.addWidget(buttons_frame)
Пример #6
0
    def __init__(self, *args, **kwargs):
        super(StringDoubleFieldWidget, self).__init__(*args, **kwargs)

        widget = QFrame(self)
        layout = layouts.HorizontalLayout(spacing=4, margins=(0, 0, 0, 0))
        widget.setLayout(layout)

        self._widget1 = lineedit.BaseLineEdit(parent=self)
        self._widget2 = lineedit.BaseLineEdit(parent=self)
        self._widget1.textChanged.connect(self._on_emit_value_changed)
        self._widget2.textChanged.connect(self._on_emit_value_changed)
        layout.addWidget(self._widget1)
        layout.addWidget(self._widget2)

        self.set_widget(widget)
Пример #7
0
    def ui(self):
        super(DoubleSpinBoxAxis, self).ui()

        axis_widget = QFrame(parent=self)
        axis_widget.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        axis_layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        axis_widget.setLayout(axis_layout)
        self._axis_btn = buttons.get_axis_button(axis_type=self._axis,
                                                 parent=self)
        self._line = BaseDoubleSpinBox(parent=self)
        self._line.setRange(self._min, self._max)
        self._line.setValue(self._start)
        axis_layout.addWidget(self._axis_btn)
        axis_layout.addWidget(self._line)

        self.main_layout.addWidget(axis_widget)
Пример #8
0
    def __init__(self, *args, **kwargs):
        super(RangeFieldWidget, self).__init__(*args, **kwargs)

        widget = QFrame(self)
        layout = layouts.HorizontalLayout(spacing=4, margins=(0, 0, 0, 0))
        widget.setLayout(layout)

        validator = QIntValidator(-50000000, 50000000, self)

        self._min_widget = lineedit.BaseLineEdit(parent=self)
        self._min_widget.setValidator(validator)
        self._min_widget.textChanged.connect(self._on_emit_value_changed)
        widget.layout().addWidget(self._min_widget)

        self._max_widget = lineedit.BaseLineEdit(parent=self)
        self._max_widget.setValidator(validator)
        self._max_widget.textChanged.connect(self._on_emit_value_changed)
        widget.layout().addWidget(self._max_widget)

        self.set_widget(widget)
Пример #9
0
    def ui(self):
        super(Project, self).ui()

        self.setMaximumWidth(qtutils.dpi_scale(160))
        self.setMaximumHeight(qtutils.dpi_scale(200))

        widget_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        main_frame = QFrame()
        main_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        main_frame.setLineWidth(1)
        main_frame.setLayout(widget_layout)
        self.main_layout.addWidget(main_frame)

        self.project_btn = QPushButton('', self)
        self.project_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.project_btn.setIconSize(QSize(120, 120))
        project_lbl = label.BaseLabel(self.name, parent=self)
        project_lbl.setObjectName('projectLabel')
        project_lbl.setAlignment(Qt.AlignCenter)
        widget_layout.addWidget(self.project_btn)
        widget_layout.addWidget(project_lbl)
Пример #10
0
    def ui(self):
        super(Template, self).ui()

        self.setMaximumWidth(160)
        self.setMaximumHeight(200)

        widget_layout = layouts.VerticalLayout(spacing=0, margins=(2, 2, 2, 2))
        main_frame = QFrame()
        main_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        main_frame.setLineWidth(1)
        main_frame.setLayout(widget_layout)
        self.main_layout.addWidget(main_frame)

        self.template_btn = QPushButton('', self)
        self.template_btn.setCheckable(True)
        self.template_btn.setIcon(self.get_icon())
        self.template_btn.setIconSize(QSize(120, 120))
        template_lbl = label.BaseLabel(self.name, parent=self)
        template_lbl.setObjectName('templateLabel')
        template_lbl.setAlignment(Qt.AlignCenter)
        widget_layout.addWidget(self.template_btn)
        widget_layout.addWidget(template_lbl)
Пример #11
0
    def ui(self):
        super(PopupMessage, self).ui()

        current_theme = self.theme()

        self.setObjectName('message')
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog
                            | Qt.WA_TranslucentBackground
                            | Qt.WA_DeleteOnClose)
        # self.setAttribute(Qt.WA_TranslucentBackground)

        if self._theme_type == MessageTypes.LOADING:
            icon_label = loading.CircleLoading.tiny(parent=self)
        else:
            icon_label = avatar.Avatar.tiny()
            current_type = self._theme_type or MessageTypes.INFO
            if current_theme:
                icon_label.image = resources.pixmap(
                    current_type,
                    color=getattr(current_theme,
                                  '{}_color'.format(current_type)))

        main_frame = QFrame(self)
        main_frame_layout = layouts.HorizontalLayout(spacing=5,
                                                     margins=(5, 5, 5, 5))
        main_frame.setLayout(main_frame_layout)
        self.main_layout.addWidget(main_frame)

        self._content_label = label.BaseLabel(parent=self)
        self._content_label.setText(self._text)

        self._close_btn = buttons.BaseToolButton(parent=self).image(
            'close', theme='window').icon_only().tiny()
        self._close_btn.setVisible(self._closable or False)

        main_frame_layout.addWidget(icon_label)
        main_frame_layout.addWidget(self._content_label)
        main_frame_layout.addStretch()
        main_frame_layout.addWidget(self._close_btn)
Пример #12
0
    def ui(self):
        super(DragDoubleSpinBoxLineAxis, self).ui()

        axis_widget = QFrame()
        axis_widget.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
        axis_layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        axis_widget.setLayout(axis_layout)
        self._axis_btn = buttons.get_axis_button(axis_type=self._axis,
                                                 parent=self)
        self._line = DragDoubleSpinBoxLine(start=self._start,
                                           max=self._max,
                                           min=self._min,
                                           positive=self._positive,
                                           parent=self)
        self._reset_btn = buttons.BaseToolButton(
            parent=self).image('reset').icon_only()
        self._reset_btn.setVisible(self._reset)
        self._reset_btn.setEnabled(self._reset)
        axis_layout.addWidget(self._axis_btn)
        axis_layout.addWidget(self._line)
        axis_layout.addWidget(self._reset_btn)

        self.main_layout.addWidget(axis_widget)
Пример #13
0
    def ui(self):
        super(NameIt, self).ui()

        tools_toolbar = toolbar.ToolBar('Main ToolBar', parent=self)
        tools_toolbar.setMovable(False)
        # tools_toolbar.setAllowedAreas(Qt.TopToolBarArea | Qt.BottomToolBarArea)
        self.main_layout.addWidget(tools_toolbar)

        refresh_btn = buttons.BaseToolButton(parent=tools_toolbar)
        refresh_btn.setIcon(resources.icon('refresh'))
        refresh_btn.clicked.connect(self._on_refresh)
        self._refresh_btn = tools_toolbar.addWidget(refresh_btn)
        self._refresh_btn.setEnabled(False)

        save_btn = buttons.BaseToolButton(parent=tools_toolbar)
        save_btn.setIcon(resources.icon('save'))
        save_btn.clicked.connect(self._on_save)
        self._save_btn = tools_toolbar.addWidget(save_btn)
        self._save_btn.setEnabled(False)

        if self._is_renamer_tool_available():
            renamer_btn = buttons.BaseToolButton(parent=tools_toolbar)
            renamer_btn.setIcon(resources.icon('rename'))
            renamer_btn.clicked.connect(self._on_open_renamer_tool)
            tools_toolbar.addWidget(renamer_btn)

        self._name_file_line = directory.SelectFile(label_text='Naming File',
                                                    parent=tools_toolbar)
        tools_toolbar.addWidget(self._name_file_line)

        base_layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        self.main_layout.addLayout(base_layout)

        panels_splitter = QSplitter(parent=self)
        panels_splitter.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
        base_layout.addWidget(panels_splitter)

        left_panel_widget = QWidget()
        left_panel_layout = layouts.VerticalLayout(margins=(5, 0, 5, 0))
        left_panel_widget.setLayout(left_panel_layout)
        panels_splitter.addWidget(left_panel_widget)

        # Tab Widget
        rules_tab = QWidget()
        tokens_tab = QWidget()
        templates_tab = QWidget()
        templates_tokens_tab = QWidget()

        self.tabs = tabs.BaseTabWidget()
        self.tabs.addTab(rules_tab, 'Rules')
        self.tabs.addTab(tokens_tab, 'Tokens')
        self.tabs.addTab(templates_tab, 'Templates')
        self.tabs.addTab(templates_tokens_tab, 'Templates Tokens')
        left_panel_layout.addWidget(self.tabs)

        # Rules Tab
        rules_main_layout = layouts.VerticalLayout(spacing=0,
                                                   margins=(5, 5, 5, 5))
        self.rules_list = QListWidget()
        rules_main_layout.addWidget(self.rules_list)
        left_panel_buttons_layout_rules = layouts.HorizontalLayout(margins=(5,
                                                                            5,
                                                                            5,
                                                                            0))
        rules_main_layout.addLayout(left_panel_buttons_layout_rules)
        self.add_rule_btn = buttons.BaseButton(parent=self)
        self.remove_rule_btn = buttons.BaseButton(parent=self)
        self.add_rule_btn.setIcon(resources.icon('plus'))
        self.remove_rule_btn.setIcon(resources.icon('minus'))
        left_panel_buttons_layout_rules.addStretch()
        left_panel_buttons_layout_rules.addWidget(self.add_rule_btn)
        left_panel_buttons_layout_rules.addWidget(self.remove_rule_btn)
        rules_tab.setLayout(rules_main_layout)

        # Tokens Tab
        tokens_main_layout = layouts.VerticalLayout(margins=(5, 5, 5, 5))
        tokens_main_layout.setSpacing(0)
        self.tokens_list = QListWidget()
        tokens_main_layout.addWidget(self.tokens_list)
        left_panel_buttons_layout_tokens = layouts.HorizontalLayout(
            margins=(5, 5, 5, 0))
        tokens_main_layout.addLayout(left_panel_buttons_layout_tokens)
        self.add_token_btn = buttons.BaseButton(parent=self)
        self.remove_token_btn = buttons.BaseButton(parent=self)
        self.add_token_btn.setIcon(resources.icon('plus'))
        self.remove_token_btn.setIcon(resources.icon('minus'))
        left_panel_buttons_layout_tokens.addStretch()
        left_panel_buttons_layout_tokens.addWidget(self.add_token_btn)
        left_panel_buttons_layout_tokens.addWidget(self.remove_token_btn)
        tokens_tab.setLayout(tokens_main_layout)

        # Templates Tab
        templates_main_layout = layouts.VerticalLayout(spacing=0,
                                                       margins=(5, 5, 5, 5))
        self.templates_list = QListWidget()
        templates_main_layout.addWidget(self.templates_list)
        left_panel_buttons_layout_templates = layouts.HorizontalLayout(
            margins=(5, 5, 5, 0))
        templates_main_layout.addLayout(left_panel_buttons_layout_templates)
        self.add_template_btn = buttons.BaseButton(parent=self)
        self.remove_template_btn = buttons.BaseButton(parent=self)
        self.add_template_btn.setIcon(resources.icon('plus'))
        self.remove_template_btn.setIcon(resources.icon('minus'))
        left_panel_buttons_layout_templates.addStretch()
        left_panel_buttons_layout_templates.addWidget(self.add_template_btn)
        left_panel_buttons_layout_templates.addWidget(self.remove_template_btn)
        templates_tab.setLayout(templates_main_layout)

        # Template Tokens Tab
        templates_tokens_main_layout = layouts.VerticalLayout(spacing=0,
                                                              margins=(5, 5, 5,
                                                                       5))
        self.template_tokens_list = QListWidget()
        templates_tokens_main_layout.addWidget(self.template_tokens_list)
        left_panel_buttons_layout_templates_tokens = layouts.HorizontalLayout(
            margins=(5, 5, 5, 0))
        left_panel_buttons_layout_templates_tokens.setContentsMargins(
            5, 5, 5, 0)
        templates_tokens_main_layout.addLayout(
            left_panel_buttons_layout_templates_tokens)
        self.add_template_token_btn = buttons.BaseButton(parent=self)
        self.remove_template_token_btn = buttons.BaseButton(parent=self)
        self.add_template_token_btn.setIcon(resources.icon('plus'))
        self.remove_template_token_btn.setIcon(resources.icon('minus'))
        left_panel_buttons_layout_templates_tokens.addStretch()
        left_panel_buttons_layout_templates_tokens.addWidget(
            self.add_template_token_btn)
        left_panel_buttons_layout_templates_tokens.addWidget(
            self.remove_template_token_btn)
        templates_tokens_tab.setLayout(templates_tokens_main_layout)

        # === PROPERTIES === #
        main_group = QGroupBox('Properties')
        panels_splitter.addWidget(main_group)

        self.group_layout = layouts.VerticalLayout(spacing=0,
                                                   margins=(5, 5, 5, 5))
        main_group.setLayout(self.group_layout)

        # Rules Panel
        self.rules_widget = QWidget(self)
        rules_layout = layouts.GridLayout()
        self.rules_widget.setLayout(rules_layout)
        expression_lbl = label.BaseLabel('Expression', parent=self)
        self.expression_line = lineedit.BaseLineEdit(parent=self)
        self.expression_btn = buttons.BaseButton('   <', parent=self)
        self.expression_btn.setEnabled(False)
        self.expression_btn.setStyleSheet(
            "QPushButton::menu-indicator{image:url(none.jpg);}")
        self.expression_menu = QMenu(self)
        self.expression_btn.setMenu(self.expression_menu)
        iterator_lbl = label.BaseLabel('Iterator', parent=self)
        self.iterator_cbx = combobox.BaseComboBox(parent=self)
        for it_format in [
                '@', '@^', '#', '##', '###', '####', '#####', 'None'
        ]:
            self.iterator_cbx.addItem(it_format)
        description_rule_lbl = label.BaseLabel('Description', parent=self)
        self.description_rule_text = QTextEdit(parent=self)
        self.group_layout.addWidget(self.rules_widget)

        rules_layout.addWidget(expression_lbl, 0, 0, Qt.AlignRight)
        rules_layout.addWidget(self.expression_line, 0, 1)
        rules_layout.addWidget(self.expression_btn, 0, 2)
        rules_layout.addWidget(iterator_lbl, 1, 0, Qt.AlignRight | Qt.AlignTop)
        rules_layout.addWidget(self.iterator_cbx, 1, 1, 1, 2)
        rules_layout.addWidget(description_rule_lbl, 2, 0,
                               Qt.AlignRight | Qt.AlignTop)
        rules_layout.addWidget(self.description_rule_text, 2, 1, 1, 2)

        # Tokens Panel
        self.tokens_widget = QWidget(parent=self)
        tokens_layout = layouts.GridLayout()
        self.tokens_widget.setLayout(tokens_layout)
        values_lbl = label.BaseLabel('Values')
        data = {'key': list(), 'value': list()}
        self.values_table = TokensTable(data, 0, 2)
        self.values_table.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Expanding)
        values_buttons_layout = layouts.HorizontalLayout(margins=(5, 5, 5, 0))
        self.add_key_value_btn = buttons.BaseButton(parent=self)
        self.remove_key_value_btn = buttons.BaseButton(parent=self)
        self.add_key_value_btn.setIcon(resources.icon('plus'))
        self.remove_key_value_btn.setIcon(resources.icon('minus'))
        values_buttons_layout.addWidget(self.add_key_value_btn)
        values_buttons_layout.addWidget(self.remove_key_value_btn)
        values_buttons_layout.addStretch()
        default_lbl = label.BaseLabel('Default', parent=self)
        self.default_cbx = combobox.BaseComboBox(parent=self)
        description_tokens_lbl = label.BaseLabel('Description', parent=self)
        self.description_token_text = QTextEdit(parent=self)
        self.group_layout.addWidget(self.tokens_widget)
        self.tokens_widget.hide()
        tokens_layout.addWidget(values_lbl, 0, 0, Qt.AlignRight | Qt.AlignTop)
        tokens_layout.addWidget(self.values_table, 0, 1, 2, 1)
        tokens_layout.addLayout(values_buttons_layout, 0, 2)
        tokens_layout.addWidget(default_lbl, 4, 0, Qt.AlignRight)
        tokens_layout.addWidget(self.default_cbx, 4, 1, 1, 2)
        tokens_layout.addWidget(description_tokens_lbl, 5, 0,
                                Qt.AlignRight | Qt.AlignTop)
        tokens_layout.addWidget(self.description_token_text, 5, 1, 1, 2)

        # Templates Panel
        self.templates_widget = QWidget(parent=self)
        templates_layout = layouts.VerticalLayout()
        self.templates_widget.setLayout(templates_layout)
        pattern_layout = layouts.HorizontalLayout(spacing=5,
                                                  margins=(5, 5, 5, 5))
        pattern_lbl = label.BaseLabel('Pattern: ', parent=self)
        self.pattern_line = lineedit.BaseLineEdit(parent=self)
        pattern_layout.addWidget(pattern_lbl)
        pattern_layout.addWidget(self.pattern_line)
        templates_layout.addLayout(pattern_layout)
        templates_layout.addLayout(dividers.DividerLayout())
        self.template_tokens_layout = layouts.GridLayout()
        self.template_tokens_layout.setAlignment(Qt.AlignTop)
        template_tokens_frame = QFrame(parent=self)
        template_tokens_frame.setFrameShape(QFrame.StyledPanel)
        template_tokens_frame.setFrameShadow(QFrame.Sunken)
        template_tokens_frame.setLayout(self.template_tokens_layout)
        templates_layout.addWidget(template_tokens_frame)
        self.group_layout.addWidget(self.templates_widget)
        self.templates_widget.hide()

        # Templates Tokens Panel
        self.templates_tokens_widget = QWidget(parent=self)
        templates_tokens_layout = layouts.VerticalLayout()
        self.templates_tokens_widget.setLayout(templates_tokens_layout)
        description_templates_token_layout = layouts.HorizontalLayout(
            spacing=5, margins=(5, 5, 5, 5))
        description_tokens_layout = layouts.VerticalLayout()
        description_templates_token_lbl = label.BaseLabel('Description: ',
                                                          parent=self)
        description_tokens_layout.addWidget(description_templates_token_lbl)
        description_tokens_layout.addStretch()
        self.description_templates_token_text = QTextEdit(parent=self)
        description_templates_token_layout.addLayout(description_tokens_layout)
        description_templates_token_layout.addWidget(
            self.description_templates_token_text)
        templates_tokens_layout.addLayout(description_templates_token_layout)
        self.group_layout.addWidget(self.templates_tokens_widget)
        self.templates_tokens_widget.hide()

        # Initialize database
        self._init_db()

        # First update of the UI
        self.update_expression_menu()
        self.update_tokens_properties_state()
        self.update_rules_properties_state()
        self.update_templates_properties_state()
Пример #14
0
class SidebarWidget(base.BaseWidget):

    itemDropped = Signal(object)
    itemRenamed = Signal(str, str)
    settingsMenuRequested = Signal(object)

    def __init__(self, parent=None):

        self._library = None
        self._previous_filter_text = ''

        super(SidebarWidget, self).__init__(parent=parent)

    # ============================================================================================================
    # OVERRIDES
    # ============================================================================================================

    def get_main_layout(self):
        return layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))

    def ui(self):
        super(SidebarWidget, self).ui()

        self._title_widget = QFrame(self)
        title_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        self._title_widget.setLayout(title_layout)

        buttons_layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        self._title_button = buttons.BaseButton(parent=self)
        self._title_button.setIcon(resources.icon('reset'))
        self._menu_button = buttons.BaseButton(parent=self)
        self._menu_button.setIcon(resources.icon('menu_dots'))
        buttons_layout.addWidget(self._title_button)
        buttons_layout.addStretch()
        buttons_layout.addWidget(self._menu_button)

        self._filter_search = search.SearchFindWidget(parent=self)
        self._filter_search.setVisible(False)

        title_layout.addLayout(buttons_layout)
        title_layout.addWidget(self._filter_search)

        self._tree_widget = SidebarTree(self)
        self._tree_widget.installEventFilter(self)
        self._tree_widget.itemDropped = self.itemDropped
        self._tree_widget.itemRenamed = self.itemRenamed
        self.itemSelectionChanged = self._tree_widget.itemSelectionChanged

        self._filter_search.set_text(self._tree_widget.filter_text())

        self.main_layout.addWidget(self._title_widget)
        self.main_layout.addWidget(self._tree_widget)

    def setup_signals(self):
        self._title_button.clicked.connect(self.clear_selection)
        self._menu_button.clicked.connect(self._on_show_settings_menu)
        self._filter_search.textChanged.connect(self._on_search_changed)

    def eventFilter(self, obj, event):
        if event.type() == QEvent.KeyPress:
            text = event.text().strip()
            if text.isalpha() or text.isdigit():
                if text and not self._filter_search.search_line.hasFocus():
                    self._filter_search.set_text(text)
                self.set_filter_visible(True)
                self._previous_filter_text = text

        return super(SidebarWidget, self).eventFilter(obj, event)

    # ============================================================================================================
    # BASE
    # ============================================================================================================

    def library(self):
        """
        Returns the library model for the menu
        :return: Library
        """

        return self._library

    def set_library(self, library):
        """
        Set the library model for the menu
        :param library: Library
        """

        if library == self._library:
            return

        self._library = library
        # self._library.dataChanged.connect(self._on_data_changed)
        # self._on_data_changed()

    def set_filter_visible(self, flag):
        """
        Sets whether or not filter widget is visible
        :param flag: bool
        """

        self._filter_search.setVisible(flag)
        self._filter_search.search_line.setFocus()
        if not flag and bool(self._tree_widget.filter_text()):
            self._tree_widget.set_filter_text('')
        else:
            self.refresh_filter()

    def search(self):
        if not self.library():
            LOGGER.info('No library found for sidebar widget')
            return

        self.library().add_query(self.query())
        self.library().search()

    def query(self):
        """
        Returns the query for the sidebar widget
        :return: dict
        """

        filters = list()

        for path in self.selected_paths():
            if self.is_recursive():
                filter_ = ('path', 'startswith', path + '/')
                filters.append(filter_)
            filter_ = ('path', 'not', path)
            filters.append(filter_)
        unique_name = 'sidebar_widget_' + str(id(self))
        return {'name': unique_name, 'operator': 'and', 'filters': filters}

    # ============================================================================================================
    # TREE HELPERS FUNCTIONS
    # ============================================================================================================

    def tree_widget(self):
        return self._tree_widget

    def set_dpi(self, dpi):
        self._tree_widget.set_dpi(dpi)

    def is_root_visible(self):
        return self._tree_widget.is_root_visible()

    def set_root_visible(self, flag):
        self._tree_widget.set_root_visible(flag)

    def filter_text(self):
        return self._tree_widget.filter_text()

    def set_filter_text(self, text):
        self._filter_search.set_text(text)

    def refresh_filter(self):
        self._tree_widget.set_filter_text(self._filter_search.get_text())

    def is_filter_visible(self):
        return bool(self._tree_widget.filter_text()) or self._filter_search.isVisible()

    def icons_visible(self):
        return self._tree_widget.icons_visible()

    def set_icons_visible(self, flag):
        self._tree_widget.set_icons_visible(flag)

    def is_recursive(self):
        return self._tree_widget.is_recursive()

    def set_recursive(self, flag):
        self._tree_widget.set_recursive(flag)

    def is_locked(self):
        return self._tree_widget.is_locked()

    def set_locked(self, flag):
        self._tree_widget.set_locked(flag)

    def set_data(self, *args, **kwargs):
        self._tree_widget.set_data(*args, **kwargs)

    def set_item_data(self, item_id, item_data):
        self._tree_widget.set_path_settings(item_id, item_data)

    def selected_path(self):
        return self._tree_widget.selected_path()

    def selected_paths(self):
        return self._tree_widget.selected_paths()

    def select_paths(self, paths):
        self._tree_widget.select_paths(paths)

    def clear_selection(self):
        self._tree_widget.clearSelection()

    # ============================================================================================================
    # SETTINGS
    # ============================================================================================================

    def settings(self):
        """
        Returns sidebar widget settings
        :return: dict
        """

        settings = self._tree_widget.settings()
        settings['filterText'] = self.filter_text()
        settings['filterVisible'] = self.is_filter_visible()

        return settings

    def set_settings(self, settings_dict):
        """
        Sets sidebar widget settings
        :param settings_dict: dict
        """

        value = settings_dict.get('filterText')
        if value is not None:
            self.set_filter_text(value)

        self._tree_widget.set_settings(settings_dict)
        value = settings_dict.get('filterVisible')
        if value is not None:
            self.set_filter_visible(value)

    # ============================================================================================================
    # INTERNAL
    # ============================================================================================================

    def _filter_visible_trigger(self, flag):
        """
        Internal function that sets filter visible
        """

        self.set_filter_visible(flag)
        self._filter_search.select_all()

    def _create_settings_menu(self, settings_menu):
        """
        Internal function that creates sidebar settings context menu
        :param settings_menu: Menu
        :return: Menu
        """

        show_filter_action = settings_menu.addAction(resources.icon('filter'), 'Show Filter')
        show_filter_action.setCheckable(True)
        show_filter_action.setChecked(self.is_filter_visible())
        show_filter_action_callback = partial(self._filter_visible_trigger, not self.is_filter_visible())
        show_filter_action.triggered.connect(show_filter_action_callback)

        show_icons_action = settings_menu.addAction(resources.icon('icons'), 'Show Icons')
        show_icons_action.setCheckable(True)
        show_icons_action.setChecked(self.icons_visible())
        show_icons_action_callback = partial(self.set_icons_visible, not self.icons_visible())
        show_icons_action.triggered.connect(show_icons_action_callback)

        show_root_folder_action = settings_menu.addAction(resources.icon('folder_tree'), 'Show Root Folder')
        show_root_folder_action.setCheckable(True)
        show_root_folder_action.setChecked(self.is_root_visible())
        show_root_folder_action_callback = partial(self.set_root_visible, not self.is_root_visible())
        show_root_folder_action.triggered.connect(show_root_folder_action_callback)

        return settings_menu

    # ============================================================================================================
    # CALLBACKS
    # ============================================================================================================

    def _on_data_changed(self):
        """
        Internal callback function that is triggered when the library data changes
        """

        pass

    def _on_search_changed(self, text):
        """
        Internal callback function called when the search filter has changed
        :param text: str
        """

        self.refresh_filter()
        if text:
            self.set_filter_visible(True)
        else:
            self._tree_widget.setFocus()
            self.set_filter_visible(False)

    def _on_show_settings_menu(self):
        settings_menu = menu.Menu(self)
        self.settingsMenuRequested.emit(settings_menu)
        self._create_settings_menu(settings_menu)
        point = QCursor.pos()
        point.setX(point.x() + 3)
        point.setY(point.y() + 3)
        settings_menu.exec_(point)
        settings_menu.close()
Пример #15
0
class StackItem(QFrame, object):

    updateRequested = Signal()

    def __init__(self,
                 title,
                 parent,
                 icon=None,
                 title_editable=True,
                 icon_size=12,
                 title_frame=None,
                 show_item_icon=True):
        super(StackItem, self).__init__(parent)

        self._stack_widget = parent
        self._icon_size = icon_size
        self._title = title
        self._title_editable = title_editable
        self._icon = icon
        self._color = consts.DARK_BG_COLOR
        self._contents_margins = (0, 0, 0, 0)
        self._contents_spacing = 0
        self._title_frame = title_frame
        self._show_item_icon = show_item_icon

        self.ui()
        self.setup_signals()

    @property
    def contents_layout(self):
        return self._contents_layout

    def ui(self):
        # theme = tpDcc.ToolsMgr().get_tool_theme('tpDcc-tools-hub')
        # border_width = qtutils.dpi_scale_divide(theme.STACK_BORDER_WIDTH)
        margin = qtutils.dpi_scale_divide(1)
        self.main_layout = layouts.VerticalLayout(margins=(margin, margin,
                                                           margin, margin),
                                                  spacing=0)
        # self.main_layout = layouts.VerticalLayout(margins=(0, 0, 0, 0), spacing=0)

        self.setLayout(self.main_layout)

        if not self._title_frame:
            self._title_frame = StackTitleFrame(
                title=self._title,
                icon=self._icon,
                title_editable=self._title_editable,
                item_icon_size=self._icon_size)
        if not self._show_item_icon:
            self._title_frame.item_icon_button.hide()

        self._contents_widget = QFrame(parent=self)
        self._contents_layout = layouts.VerticalLayout(
            spacing=self._contents_spacing, margins=self._contents_margins)
        self._contents_widget.setLayout(self._contents_layout)

        self.main_layout.addWidget(self._title_frame)
        self.main_layout.addWidget(self._contents_widget)

    def setup_signals(self):
        self._title_frame.updateRequested.connect(self.updateRequested.emit)

    def title_text_widget(self):
        """
        Returns title text widget
        :return: QLineEdit
        """

        return self._title_frame.line_edit

    def get_title(self):
        """
        Returns title text
        :return: str
        """

        return self._title_frame.line_edit.text()

    def set_title(self, text):
        """
        Function that sets title text
        :param text: str
        """

        self._title_frame.line_edit.setText(text)

    def add_widget(self, widget):
        """
        Adds a new widget to the contents layout
        :param widget: QWidget
        """

        self._contents_layout.addWidget(widget)

    def add_layout(self, layout):
        """
        Adds a new layout to the contents layout
        :param layout: QLayout
        """

        self._contents_layout.addLayout(layout)

    def set_title_text_mouse_transparent(self, flag):
        """
        Sets whether or not title text mouse is transparent
        :param flag: bool
        """

        self._title_frame.line_edit.setAttribute(
            Qt.WA_TransparentForMouseEvents, flag)

    def set_item_icon_color(self, color):
        """
        Sets the color of the item in title
        :param color: tuple(int, int, int), RGB color in 0-255 range
        """

        self._title_frame.set_item_icon_color(color)

    def set_item_icon(self, icon):
        """
        Sets the icon of the item in title
        :param icon: QIcon
        """

        self.title_frame.set_item_icon(icon)

    def update_size(self):
        """
        Updates the size of the widget, to fit to new size depending on its contents
        """

        self.updateRequested.emit()
Пример #16
0
class PreviewWidget(base.BaseWidget, object):
    def __init__(self, item_view, parent=None):

        self._item_view = item_view
        self._sequence_widget = None
        self._form_widget = None

        super(PreviewWidget, self).__init__(parent=parent)

        self._create_sequence_widget()

    # ============================================================================================================
    # OVERRIDES
    # ============================================================================================================

    def get_main_layout(self):
        main_layout = layouts.VerticalLayout(spacing=2, margins=(0, 0, 0, 0))
        main_layout.setAlignment(Qt.AlignTop)

        return main_layout

    def ui(self):
        super(PreviewWidget, self).ui()

        title_frame = QFrame(self)
        title_frame_layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        title_frame.setLayout(title_frame_layout)
        title_widget = QWidget(self)
        title_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        title_widget.setLayout(title_layout)
        buttons_layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        title_layout.addLayout(buttons_layout)
        self._title_icon = label.BaseLabel(parent=self)
        self._title_button = label.ElidedLabel(parent=self)
        self._title_button.setText(self.item().name())
        self._menu_button = buttons.BaseButton(parent=self)
        self._menu_button.setIcon(resources.icon('menu_dots'))
        buttons_layout.addWidget(self._title_icon)
        buttons_layout.addStretch()
        buttons_layout.addWidget(self._title_button)
        buttons_layout.addStretch()
        buttons_layout.addWidget(self._menu_button)
        title_frame_layout.addWidget(title_widget)

        item_icon_name = self.item().icon() or 'tpDcc'
        item_icon = resources.icon(item_icon_name)
        if not item_icon:
            item_icon = resources.icon('tpDcc')
        self._title_icon.setPixmap(item_icon.pixmap(QSize(20, 20)))

        icon_title_frame = QFrame(self)
        icon_title_frame_layout = layouts.VerticalLayout(spacing=0, margins=(4, 2, 4, 2))
        icon_title_frame.setLayout(icon_title_frame_layout)

        self._icon_group_frame = QFrame(self)
        icon_group_layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        self._icon_group_frame.setLayout(icon_group_layout)
        self._icon_frame = QFrame(self)
        icon_frame_layout = layouts.VerticalLayout(spacing=0, margins=(4, 2, 4, 2))
        self._icon_frame.setLayout(icon_frame_layout)
        icon_group_layout.addWidget(self._icon_frame)
        icon_group_box_widget = group.GroupBoxWidget('Icon', widget=self._icon_group_frame, parent=self)
        icon_title_frame_layout.addWidget(icon_group_box_widget)

        form_frame = QFrame(self)
        form_frame_layout = layouts.VerticalLayout(spacing=0, margins=(4, 2, 4, 2))
        form_frame.setLayout(form_frame_layout)

        buttons_frame = QFrame(self)
        buttons_frame_layout = layouts.HorizontalLayout(spacing=4, margins=(4, 4, 4, 4))
        buttons_frame.setLayout(buttons_frame_layout)

        self._accept_button = buttons.BaseButton('Load')
        self._accept_button.setIcon(resources.icon('open'))
        self._accept_button.setVisible(False)
        buttons_frame_layout.addWidget(self._accept_button)

        schema = self._item_view.item.load_schema() if self._item_view else None
        if schema:
            self._form_widget = formwidget.FormWidget(self)
            self._form_widget.setObjectName('{}Form'.format(self._item_view.__class__.__name__))
            self._form_widget.set_schema(schema)
            self._form_widget.set_validator(self.validator)
            form_frame_layout.addWidget(self._form_widget)

        self.main_layout.addWidget(title_frame)
        self.main_layout.addWidget(icon_title_frame)
        self.main_layout.addWidget(self._icon_group_frame)
        self.main_layout.addWidget(form_frame)
        self.main_layout.addStretch()
        self.main_layout.addWidget(buttons_frame)

    def setup_signals(self):
        self._menu_button.clicked.connect(self._on_show_menu)
        self._accept_button.clicked.connect(self.on_load)

    def resizeEvent(self, event):
        """
        Overrides base BaseWidget resizeEvent function to make sure the icon image size is updated
        :param event: QSizeEvent
        """

        self.update_thumbnail_size()

    def close(self):
        """
        Overrides base BaseWidget close function to save widget persistent data
        """

        # TODO: It is not sure this function it is going to be called when the app is closed
        # TODO: Find a better approach

        if self._form_widget:
            self._form_widget.save_persistent_values()

        super(PreviewWidget, self).close()

    # ============================================================================================================
    # BASE
    # ============================================================================================================

    def item(self):
        """
        Returns the library item to load
        :return: LibraryItem
        """

        return self._item_view

    def validator(self, **kwargs):
        """
        Returns validator used for validating the item loaded arguments
        :param kwargs: dict
        """

        self._item_view.load_validator(**kwargs)
        self.update_icon()

    def update_icon(self):
        """
        Updates item thumbnail icon
        """

        # Updates static icon
        icon = self._item_view.thumbnail_icon()
        if icon:
            self._sequence_widget.setIcon(icon)

        # Update images sequence (if exist)
        if self._item_view.image_sequence_path():
            self._sequence_widget.set_dirname(self._item_view.image_sequence_path())

    def update_thumbnail_size(self):
        """
        Updates the thumbnail button to the size of the widget
        """

        width = self.width() - 5
        width = width if width <= 150 else 150
        size = QSize(width, width)
        self._icon_frame.setMaximumSize(size)
        self._icon_group_frame.setMaximumSize(size)

        if self._sequence_widget:
            self._sequence_widget.setIconSize(size)
            self._sequence_widget.setMinimumSize(size)
            self._sequence_widget.setMaximumSize(size)

    # ============================================================================================================
    # INTERNAL
    # ============================================================================================================

    def _create_sequence_widget(self):
        """
        Internal function that creates sequence widget for the item
        """

        self._sequence_widget = sequence.ImageSequenceWidget(self._icon_frame)
        self._icon_frame.layout().insertWidget(0, self._sequence_widget)
        self.update_icon()

    # ============================================================================================================
    # CALLBACKS
    # ============================================================================================================

    def _on_item_data_changed(self, *args, **kwargs):
        """
        Internal callback function that is called when item data changes
        :param args:
        :param kwargs:
        """

        self.update_icon()

    def _on_show_menu(self):
        """
        Internal callback function triggered when item menu should be opened
        :return: QAction
        """

        menu = QMenu(self)
        self.item().context_edit_menu(menu)
        point = QCursor.pos()
        point.setX(point.x() + 3)
        point.setY(point.y() + 3)

        return menu.exec_(point)

    def on_load(self):
        """
        Internal callback function that is triggered when load button is pressed by the user
        """

        kwargs = self._form_widget.values()
        self._item_view.load(**kwargs)
Пример #17
0
class IndexedStringsWidget(QWidget):
    """ Holds the list of indexed string attributes """
    def __init__(self, data, parent=None):
        QWidget.__init__(self, parent)
        self.data = data

        vbox = QVBoxLayout()
        self.setLayout(vbox)
        title = QLabel('Indexed Strings')
        vbox.addWidget(title)

        self.frame = QFrame()
        vbox.addWidget(self.frame)
        self.vbox = QVBoxLayout()
        self.frame.setLayout(self.vbox)
        self.frame.setFrameShape(QFrame.Panel)
        self.frame.setFrameShadow(QFrame.Sunken)

        self.table = QTableWidget()
        self.table.horizontalHeader().hide()
        self.vbox.addWidget(self.table)
        self.table.hide()

        self.noStringsLabel = QLabel('<i>No indexed strings</i>')
        self.vbox.addWidget(self.noStringsLabel)

        self.widgets = []
        self.populate()

        self.data.attributeAdded.connect(self.attributeAddedSlot)
        self.data.dataReset.connect(self.dataResetSlot)
        self.data.dirtied.connect(self.dataDirtiedSlot)

    def dataDirtiedSlot(self, dirty):
        """ SLOT when the particle data is dirtied or cleaned."""
        if not dirty:
            for widget in self.widgets:
                widget.drawBorder(False)

    def dataResetSlot(self):
        """ SLOT when particle data is reconstructed """
        self.populate()

    def attributeAddedSlot(self, name):  #pylint:disable=W0613
        """ SLOT when an attribute is added to the particle set """
        attr = self.data.attributeInfo(name)
        if attr.type == partio.INDEXEDSTR:
            self.populate()

    def populate(self):
        """ Populates the table of indexed strings """

        self.widgets = []

        # If no widgets, just drop that in
        attrs = []
        for anum in range(self.data.numAttributes()):
            attr = self.data.attributeInfo(anum)
            if attr.type == partio.INDEXEDSTR:
                attrs.append(attr)

        if not attrs:
            self.table.hide()
            self.noStringsLabel.show()
            return

        self.table.show()
        self.noStringsLabel.hide()
        self.table.setColumnCount(1)
        self.table.setRowCount(len(attrs))

        for row, attr in enumerate(attrs):
            item = QTableWidgetItem(attr.name)
            self.table.setVerticalHeaderItem(row, item)
            strings = self.data.indexedStrs(attr)
            table = QTableWidget()
            table.setColumnCount(1)
            table.setRowCount(len(strings))
            table.horizontalHeader().hide()
            table.setVerticalHeaderLabels(
                [str(i) for i in range(len(strings))])
            for i, string in enumerate(strings):
                widget = QLabel(string)
                table.setCellWidget(i, 0, widget)
                self.widgets.append(widget)
            self.table.setCellWidget(row, 0, table)

        self.table.horizontalHeader().setStretchLastSection(False)
        self.table.setTabKeyNavigation(True)
        self.table.horizontalHeader().setSectionsMovable(False)

        self.table.horizontalHeader().resizeSections(
            QHeaderView.ResizeToContents)
        self.table.verticalHeader().resizeSections(
            QHeaderView.ResizeToContents)
Пример #18
0
class BaseSaveWidget(base.BaseWidget, object):

    cancelled = Signal()
    saved = Signal()

    ENABLE_THUMBNAIL_CAPTURE = True

    def __init__(self, item_view, client=None, *args, **kwargs):

        self._item_view = item_view
        self._client = client
        self._form_widget = None
        self._sequence_widget = None

        super(BaseSaveWidget, self).__init__(*args, **kwargs)

        self.setObjectName('LibrarySaveWidget')

        self._create_sequence_widget()
        self.update_thumbnail_size()
        self.set_item_view(item_view)

    # ============================================================================================================
    # OVERRIDES
    # ============================================================================================================

    def get_main_layout(self):
        return layouts.VerticalLayout(spacing=4, margins=(0, 0, 0, 0))

    def ui(self):
        super(BaseSaveWidget, self).ui()

        self.setWindowTitle('Save Item')

        title_frame = QFrame(self)
        title_frame_layout = layouts.VerticalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        title_frame.setLayout(title_frame_layout)
        title_widget = QFrame(self)
        title_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        title_widget.setLayout(title_layout)
        title_buttons_layout = layouts.HorizontalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        title_layout.addLayout(title_buttons_layout)
        title_icon = label.BaseLabel(parent=self)
        title_button = label.BaseLabel(self.item().menu_name(), parent=self)
        title_button.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Preferred)
        self._menu_button = buttons.BaseButton(parent=self)
        self._menu_button.setIcon(resources.icon('menu_dots'))
        self._menu_button.setVisible(False)  # Hide by default
        title_buttons_layout.addWidget(title_icon)
        title_buttons_layout.addSpacing(5)
        title_buttons_layout.addWidget(title_button)
        title_buttons_layout.addWidget(self._menu_button)
        title_frame_layout.addWidget(title_widget)

        item_icon_name = self.item().icon() or 'tpDcc'
        item_icon = resources.icon(item_icon_name)
        if not item_icon:
            item_icon = resources.icon('tpDcc')
        title_icon.setPixmap(item_icon.pixmap(QSize(20, 20)))

        thumbnail_layout = layouts.HorizontalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        self._thumbnail_frame = QFrame(self)
        thumbnail_frame_layout = layouts.VerticalLayout(spacing=0,
                                                        margins=(0, 2, 0, 2))
        self._thumbnail_frame.setLayout(thumbnail_frame_layout)
        thumbnail_layout.addWidget(self._thumbnail_frame)

        self._options_frame = QFrame(self)
        options_frame_layout = layouts.VerticalLayout(spacing=0,
                                                      margins=(4, 2, 4, 2))
        self._options_frame.setLayout(options_frame_layout)

        preview_buttons_frame = QFrame(self)
        self._preview_buttons_layout = layouts.HorizontalLayout(spacing=0,
                                                                margins=(4, 2,
                                                                         4, 2))
        preview_buttons_frame.setLayout(self._preview_buttons_layout)
        self._save_button = buttons.BaseButton('Save', parent=self)
        self._save_button.setIcon(resources.icon('save'))
        self._cancel_button = buttons.BaseButton('Cancel', parent=self)
        self._cancel_button.setIcon(resources.icon('cancel'))
        self._preview_buttons_layout.addStretch()
        self._preview_buttons_layout.addWidget(self._save_button)
        self._preview_buttons_layout.addStretch()
        self._preview_buttons_layout.addWidget(self._cancel_button)
        self._preview_buttons_layout.addStretch()

        self.main_layout.addWidget(title_frame)
        self.main_layout.addLayout(thumbnail_layout)
        self.main_layout.addWidget(self._options_frame)
        self.main_layout.addWidget(preview_buttons_frame)

    def setup_signals(self):
        self._menu_button.clicked.connect(self._on_show_menu)
        self._save_button.clicked.connect(self._on_save)
        self._cancel_button.clicked.connect(self._on_cancel)

    def resizeEvent(self, event):
        """
        Overrides base QWidget resizeEvent function
        :param event: QResizeEvent
        """

        self.update_thumbnail_size()

    def close(self):
        """
        Overrides base QWidget close function to disable script job when its is done
        """

        if self._form_widget:
            self._form_widget.save_persistent_values()

        super(BaseSaveWidget, self).close()

    # ============================================================================================================
    # BASE
    # ============================================================================================================

    def folder_path(self):
        """
        Returns the folder path
        :return: str
        """

        return self.form_widget().value('folder')

    def set_folder_path(self, path):
        """
        Sets the destination folder path
        :param path: str
        """

        self.form_widget().set_value('folder', path)

    def set_thumbnail_path(self, path):
        """
        Sets the path to the thumbnail image or the image sequence directory
        :param path: str
        """

        file_name, extension = os.path.splitext(path)
        target = utils.temp_path('thumbnail{}'.format(extension))
        utils.copy_path(path, target, force=True)

        self._sequence_widget.set_path(target)

    def library_window(self):
        """
        Returns library widget window for the item
        :return: LibraryWindow
        """

        return self.item_view().library_window()

    def set_library_window(self, library_window):
        """
        Sets the library widget for the item
        :param library_window: LibraryWindow
        """

        self.item_view().set_library_window(library_window)

    def form_widget(self):
        """
        Returns the form widget instance
        :return: FormWidget
        """

        return self._form_widget

    def item(self):
        """
        Returns current item
        :return:
        """

        return self.item_view().item

    def item_view(self):
        """
        Returns the current item view
        :return: LibraryItem
        """

        return self._item_view

    def set_item_view(self, item_view):
        """
        Sets the base item to be created
        :param item_view: LibraryItem
        """

        self._item_view = item_view

        if os.path.exists(item_view.image_sequence_path()):
            self.set_thumbnail_path(item_view.image_sequence_path())
        elif not item_view.is_default_thumbnail_path():
            self.set_thumbnail_path(item_view.thumbnail_path())

        schema = self.item().save_schema()
        if schema:
            form_widget = formwidget.FormWidget(self)
            form_widget.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
            form_widget.set_schema(schema)
            form_widget.set_validator(self.item().save_validator)
            # item_name = os.path.basename(item.path())
            # form_widget.set_values({'name': item_name})
            self._options_frame.layout().addWidget(form_widget)
            form_widget.validate()
            self._form_widget = form_widget
        else:
            self._options_frame.setVisible(False)

    def update_thumbnail_size(self):
        """
        Updates the thumbnail button to teh size of the widget
        """

        width = self.width() - 10
        if width > 250:
            width = 250
        size = QSize(width, width)
        if self._sequence_widget:
            self._sequence_widget.setIconSize(size)
            self._sequence_widget.setMaximumSize(size)
        self._thumbnail_frame.setMaximumSize(size)

    def show_thumbnail_capture_dialog(self):
        """
        Asks the user if they would like to capture a thumbnail
        :return: int
        """

        buttons = QDialogButtonBox.Yes | QDialogButtonBox.Ignore | QDialogButtonBox.Cancel
        parent = self.item_view().library_window()
        btn = messagebox.MessageBox.question(
            parent,
            'Create a thumbnail',
            'Would you like to capture a thumbnail?',
            buttons=buttons)
        if btn == QDialogButtonBox.Yes:
            self.thumbnail_capture()

        return btn

    def show_by_frame_dialog(self):
        """
        Show the by frame dialog
        """

        help_text = """
        To help speed up the playblast you can set the "by frame" to another greater than 1.
        For example if the "by frame" is set to 2 it will playblast every second frame
        """

        result = None
        options = self.form_widget().values()
        by_frame = options.get('byFrame', 1)
        start_frame, end_frame = options.get('frameRange', [None, None])

        duration = end_frame - start_frame if start_frame is not None and end_frame is not None else 1
        if duration > 100 and by_frame == 1:
            buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
            result = messagebox.MessageBox.question(
                self.library_window(),
                title='Tip',
                text=help_text,
                buttons=buttons,
                enable_dont_show_checkbox=True)

        return result

    def thumbnail_capture(self, show=False):
        """
        Captures a playblast and saves it to the temporal thumbnail path
        :param show: bool
        """

        options = self.form_widget().values()
        start_frame, end_frame = options.get('frameRange', [None, None])
        step = options.get('byFrame', 1)

        if not qtutils.is_control_modifier():
            result = self.show_by_frame_dialog()
            if result == QDialogButtonBox.Cancel:
                return

        path = utils.temp_path('sequence', 'thumbnail.jpg')

        try:
            snapshot.SnapshotWindow(path=path,
                                    on_save=self._on_thumbnail_captured)
            # thumbnail.ThumbnailCaptureDialog.thumbnail_capture(
            #     path=self._temp_path,
            #     show=show,
            #     start_frame=start_frame,
            #     end_frame=end_frame,
            #     step=step,
            #     clear_cache=False,
            #     captured=self._on_thumbnail_captured
            # )
        except Exception as e:
            messagebox.MessageBox.critical(self.library_window(),
                                           'Error while capturing thumbnail',
                                           str(e))
            LOGGER.error(traceback.format_exc())

    def save(self, path, thumbnail):
        """
        Saves the item with the given objects to the given disk location path
        :param path: str
        :param thumbnail: str
        """

        kwargs = self.form_widget().values()
        sequence_path = self._sequence_widget.dirname()
        item_view = self.item_view()
        item_view.item_view.path = path
        library_window = self.library_window()
        valid_save = item_view.safe_save(thumbnail=thumbnail,
                                         sequence_path=sequence_path,
                                         **kwargs)
        if valid_save:
            if library_window:
                library_window.refresh()
                library_window.select_folder_path(path)
            self.saved.emit()
        self.close()

    # ============================================================================================================
    # INTERNAL
    # ============================================================================================================

    def _create_sequence_widget(self):
        """
        Internal function that creates a sequence widget to replace the static thumbnail widget
        """

        self._sequence_widget = sequence.ImageSequenceWidget(self)
        self._sequence_widget.setObjectName('thumbnailButton')
        self._thumbnail_frame.layout().insertWidget(0, self._sequence_widget)
        self._sequence_widget.clicked.connect(self._on_thumbnail_capture)
        self._sequence_widget.setToolTip(
            'Click to capture a thumbnail from the current model panel.\n'
            'CTRL + Click to show the capture window for better framing.')

        camera_icon = resources.get('icons',
                                    self.theme().style(), 'camera.png')
        expand_icon = resources.get('icons',
                                    self.theme().style(), 'full_screen.png')
        folder_icon = resources.get('icons',
                                    self.theme().style(), 'folder.png')

        self._sequence_widget.addAction(camera_icon, 'Capture new image',
                                        'Capture new image',
                                        self._on_thumbnail_capture)
        self._sequence_widget.addAction(expand_icon, 'Show Capture window',
                                        'Show Capture window',
                                        self._on_show_capture_window)
        self._sequence_widget.addAction(folder_icon, 'Load image from disk',
                                        'Load image from disk',
                                        self._on_show_browse_image_dialog)

        self._sequence_widget.setIcon(resources.icon('tpdcc'))

    # ============================================================================================================
    # CALLBACKS
    # ============================================================================================================

    def _on_show_menu(self):
        """
        Internal callback function that is called when menu button is clicked byu the user
        :return: QAction
        """

        pass

    def _on_save(self):
        if not self.library_window():
            return False

        library = self.library_window().library()
        if not library:
            return False

        try:
            self.form_widget().validate()
            if self.form_widget().has_errors():
                raise Exception('\n'.join(self.form_widget().errors()))
            has_frames = self._sequence_widget.has_frames()
            if not has_frames and self.ENABLE_THUMBNAIL_CAPTURE:
                button = self.show_thumbnail_capture_dialog()
                if button == QDialogButtonBox.Cancel:
                    return False
            name = self.form_widget().value('name')
            folder = self.form_widget().value('folder')
            comment = self.form_widget().value('comment') or ''

            extension = self.item().extension()
            if extension and not name.endswith(extension):
                name = '{}{}'.format(name, extension)

            path = folder + '/' + name
            thumbnail = self._sequence_widget.first_frame()

            save_item = library.get(path, only_extension=True)
            save_function = save_item.functionality().get('save')
            if not save_function:
                LOGGER.warning(
                    'Item "{}" does not supports save operation'.format(
                        save_item))
                return False

            library_path = self.item().library.identifier
            if not library_path or not os.path.isfile(library_path):
                LOGGER.warning(
                    'Impossible to save data "{}" because its library does not exists: "{}"'
                    .format(self.item(), library_path))
                return

            values = self.form_widget().values()
            try:
                if self._client:
                    success, message, dependencies = self._client().save_data(
                        library_path=library_path,
                        data_path=path,
                        values=values)
                    if not success:
                        messagebox.MessageBox.critical(self.library_window(),
                                                       'Error while saving',
                                                       str(message))
                        LOGGER.error(str(message))
                        return False
                else:
                    dependencies = save_function(**values)
            except Exception as exc:
                messagebox.MessageBox.critical(self.library_window(),
                                               'Error while saving', str(exc))
                LOGGER.error(traceback.format_exc())
                return False

        except Exception as exc:
            messagebox.MessageBox.critical(self.library_window(),
                                           'Error while saving', str(exc))
            LOGGER.error(traceback.format_exc())
            raise

        new_item_path = save_item.format_identifier()
        if not new_item_path or not os.path.isfile(new_item_path):
            LOGGER.warning(
                'Although saving process for item "{}" was completed, '
                'it seems no new data has been generated!'.format(save_item))
            self.saved.emit()
            return False

        save_item.library.add(new_item_path)

        # # TODO: Instead of creating a local version, we will use a git system to upload our data to our project repo
        # # TODO: Should we save new versions of dependencies too?
        # valid = save_item.create_version(comment=comment)
        # if not valid:
        #     LOGGER.warning('Impossible to store new version for data "{}"'.format(save_item))

        if thumbnail and os.path.isfile(thumbnail):
            save_item.store_thumbnail(thumbnail)

        self.library_window().sync()

        save_item.update_dependencies(dependencies=dependencies)

        self.saved.emit()

        return True

    def _on_cancel(self):
        self.cancelled.emit()
        self.close()

    def _on_thumbnail_capture(self):
        """
        Internal callback function that is called when a thumbnail capture must be done
        """

        self.thumbnail_capture(show=False)

    def _on_thumbnail_captured(self, captured_path):
        """
        Internal callback function that is called when thumbnail is captured
        :param captured_path: str
        """

        thumb_path = os.path.dirname(captured_path)
        self.set_thumbnail_path(thumb_path)

    def _on_show_capture_window(self):
        """
        Internal callback function that shows the capture window for framing
        """

        self.thumbnail_capture(show=True)

    def _on_show_browse_image_dialog(self):
        """
        Internal callback function that shows a file dialog for choosing an image from disk
        """

        file_dialog = QFileDialog(self,
                                  caption='Open Image',
                                  filter='Image Files (*.png *.jpg)')
        file_dialog.fileSelected.connect(self.set_thumbnail_path)
        file_dialog.exec_()
Пример #19
0
class RadioFieldWidget(FieldWidget, object):
    def __init__(self, *args, **kwargs):
        super(RadioFieldWidget ,self).__init__(*args, **kwargs)

        self._radio_buttons = list()

        layout = layouts.VerticalLayout(margins=(0, 0, 0, 0))
        self._radio_frame = QFrame(self)
        self._radio_frame.setLayout(layout)

        self.set_widget(self._radio_frame)

        self.label().setStyleSheet('margin-top: 2px;')
        self.label().setAlignment(Qt.AlignRight | Qt.AlignTop)
        self.widget().setStyleSheet('margin-top: 2px;')

    # =================================================================================================================
    # OVERRIDES
    # =================================================================================================================

    def value(self):
        """
        Implements FieldWidget value function
        Returns the path of the image in disk
        :return: str
        """

        for radio_button in self._radio_buttons:
            if radio_button.isChecked():
                return radio_button.text()

        return ''

    def set_value(self, value):
        """
        Overrides FileWidget set_value function
        Sets the path of the image in disk
        :param value: str
        """

        for radio_button in self._radio_buttons:
            checked = radio_button.text() == value
            radio_button.setChecked(checked)

    def set_items(self, items):
        """
        Sets the items for the field widget
        :param items: list(str)
        """

        self.clear()

        for item in items:
            widget = buttons.BaseRadioButton(parent=self)
            widget.setText(item)
            widget.clicked.connect(self._on_emit_value_changed)
            self._radio_buttons.append(widget)
            self._radio_frame.layout().addWidget(widget)

    # =================================================================================================================
    # BASE
    # =================================================================================================================

    def clear(self):
        """
        Destroy all radio buttons
        """

        for radio_button in self._radio_buttons:
            radio_button.destroy()
            radio_button.close()
            radio_button.hide()
Пример #20
0
    def ui(self):
        super(BaseLoadWidget, self).ui()

        self.setWindowTitle('Load Item')

        title_frame = QFrame(self)
        title_frame_layout = layouts.VerticalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        title_frame.setLayout(title_frame_layout)
        title_widget = QFrame(self)
        title_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        title_widget.setLayout(title_layout)
        title_buttons_layout = layouts.HorizontalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        title_layout.addLayout(title_buttons_layout)
        title_icon = label.BaseLabel(parent=self)
        title_button = label.BaseLabel(self.item().label(), parent=self)
        title_button.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Preferred)
        self._menu_button = buttons.BaseButton(parent=self)
        self._menu_button.setIcon(resources.icon('menu_dots'))
        title_buttons_layout.addWidget(title_icon)
        title_buttons_layout.addWidget(title_button)
        title_buttons_layout.addWidget(self._menu_button)
        title_frame_layout.addWidget(title_widget)

        item_icon_name = self.item().icon() or 'tpDcc'
        item_icon = resources.icon(item_icon_name)
        if not item_icon:
            item_icon = resources.icon('tpDcc')
        title_icon.setPixmap(item_icon.pixmap(QSize(20, 20)))

        main_frame = QFrame(self)
        main_frame_layout = layouts.VerticalLayout(spacing=0,
                                                   margins=(0, 0, 0, 0))
        main_frame.setLayout(main_frame_layout)
        icon_frame = QFrame(self)
        icon_frame_layout = layouts.VerticalLayout(spacing=0,
                                                   margins=(0, 0, 0, 0))
        icon_frame.setLayout(icon_frame_layout)
        icon_title_frame = QFrame(self)
        icon_title_frame_layout = layouts.VerticalLayout(spacing=0,
                                                         margins=(0, 0, 0, 0))
        icon_frame_layout.addWidget(icon_title_frame)
        icon_title_frame.setLayout(icon_title_frame_layout)
        icon_frame2 = QFrame(self)
        icon_frame2_layout = layouts.VerticalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        icon_frame2.setLayout(icon_frame2_layout)
        thumbnail_layout = layouts.HorizontalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        self._thumbnail_frame = QFrame(self)
        thumbnail_frame_layout = layouts.VerticalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        self._thumbnail_frame.setLayout(thumbnail_frame_layout)
        icon_frame_layout.addWidget(icon_frame2)
        icon_frame2_layout.addLayout(thumbnail_layout)
        thumbnail_layout.addWidget(self._thumbnail_frame)
        form_frame = QFrame(self)
        form_frame_layout = layouts.VerticalLayout(spacing=0,
                                                   margins=(0, 0, 0, 0))
        form_frame.setLayout(form_frame_layout)
        main_frame_layout.addWidget(icon_frame)
        main_frame_layout.addWidget(form_frame)

        version_frame = QFrame(self)
        version_frame_layout = layouts.VerticalLayout(spacing=0,
                                                      margins=(0, 0, 0, 0))
        version_frame.setLayout(version_frame_layout)
        self._versions_widget = version.VersionHistoryWidget(parent=self)
        version_frame_layout.addWidget(self._versions_widget)

        self._custom_widget_frame = QFrame(self)
        custom_widget_layout = layouts.VerticalLayout(spacing=0,
                                                      margins=(0, 0, 0, 0))
        self._custom_widget_frame.setLayout(custom_widget_layout)

        self._preview_buttons_frame = QFrame(self)
        preview_buttons_layout = layouts.HorizontalLayout(spacing=2,
                                                          margins=(0, 0, 0, 0))
        self._preview_buttons_frame.setLayout(preview_buttons_layout)
        self._accept_button = buttons.BaseButton('Load', parent=self)
        self._accept_button.setIcon(resources.icon('open'))
        preview_buttons_layout.addStretch()
        preview_buttons_layout.addWidget(self._accept_button)
        preview_buttons_layout.addStretch()

        self._export_btn = buttons.BaseButton('Export', parent=self)
        self._export_btn.setIcon(resources.icon('export'))
        self._import_btn = buttons.BaseButton('Import', parent=self)
        self._import_btn.setIcon(resources.icon('import'))
        self._reference_btn = buttons.BaseButton('Reference', parent=self)
        self._reference_btn.setIcon(resources.icon('reference'))
        for btn in [self._export_btn, self._import_btn, self._reference_btn]:
            btn.setToolTip(btn.text())
        extra_buttons_frame = QFrame(self)
        extra_buttons_layout = layouts.HorizontalLayout(spacing=2,
                                                        margins=(0, 0, 0, 0))
        extra_buttons_frame.setLayout(extra_buttons_layout)
        extra_buttons_layout.addWidget(self._export_btn)
        extra_buttons_layout.addWidget(self._import_btn)
        extra_buttons_layout.addWidget(self._reference_btn)

        group_box = group.GroupBoxWidget('Icon', icon_frame)
        group_box.set_persistent(True)
        group_box.set_checked(True)

        self._version_box = group.GroupBoxWidget('Version', version_frame)
        self._version_box.set_persistent(True)
        self._version_box.set_checked(True)

        self._sequence_widget = sequence.ImageSequenceWidget(self)
        thumbnail_frame_layout.insertWidget(0, self._sequence_widget)

        if os.path.exists(self._item_view.image_sequence_path()):
            self._sequence_widget.set_path(
                self._item_view.image_sequence_path())
        elif os.path.exists(self._item_view.thumbnail_path()):
            self._sequence_widget.set_path(self._item_view.thumbnail_path())

        self._form_widget = formwidget.FormWidget(self)
        self._form_widget.set_schema(self.item().load_schema())
        self._form_widget.set_validator(self.item().load_validator)
        form_frame_layout.addWidget(self._form_widget)

        self.main_layout.addWidget(title_frame)
        self.main_layout.addWidget(group_box)
        self.main_layout.addWidget(main_frame)
        self.main_layout.addWidget(self._version_box)
        self.main_layout.addWidget(version_frame)
        self.main_layout.addWidget(self._custom_widget_frame)
        self.main_layout.addStretch()
        self.main_layout.addWidget(dividers.Divider())
        self.main_layout.addWidget(self._preview_buttons_frame)
        self.main_layout.addWidget(extra_buttons_frame)
Пример #21
0
class BaseLoadWidget(base.BaseWidget, object):
    def __init__(self, item_view, client=None, parent=None):

        self._item_view = item_view
        self._client = client
        self._form_widget = None
        self._sequence_widget = None

        super(BaseLoadWidget, self).__init__(parent=parent)

        self.setObjectName('LoadWidget')

        try:
            self.form_widget().validate()

        except NameError as error:
            LOGGER.exception(error)

        self.update_thumbnail_size()

        item = self.item()
        if item:
            self._accept_button.setVisible(
                bool(item.functionality().get('load', False)))
            self._update_version_info()

    # ============================================================================================================
    # OVERRIDES
    # ============================================================================================================

    def get_main_layout(self):
        return layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))

    def ui(self):
        super(BaseLoadWidget, self).ui()

        self.setWindowTitle('Load Item')

        title_frame = QFrame(self)
        title_frame_layout = layouts.VerticalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        title_frame.setLayout(title_frame_layout)
        title_widget = QFrame(self)
        title_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        title_widget.setLayout(title_layout)
        title_buttons_layout = layouts.HorizontalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        title_layout.addLayout(title_buttons_layout)
        title_icon = label.BaseLabel(parent=self)
        title_button = label.BaseLabel(self.item().label(), parent=self)
        title_button.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Preferred)
        self._menu_button = buttons.BaseButton(parent=self)
        self._menu_button.setIcon(resources.icon('menu_dots'))
        title_buttons_layout.addWidget(title_icon)
        title_buttons_layout.addWidget(title_button)
        title_buttons_layout.addWidget(self._menu_button)
        title_frame_layout.addWidget(title_widget)

        item_icon_name = self.item().icon() or 'tpDcc'
        item_icon = resources.icon(item_icon_name)
        if not item_icon:
            item_icon = resources.icon('tpDcc')
        title_icon.setPixmap(item_icon.pixmap(QSize(20, 20)))

        main_frame = QFrame(self)
        main_frame_layout = layouts.VerticalLayout(spacing=0,
                                                   margins=(0, 0, 0, 0))
        main_frame.setLayout(main_frame_layout)
        icon_frame = QFrame(self)
        icon_frame_layout = layouts.VerticalLayout(spacing=0,
                                                   margins=(0, 0, 0, 0))
        icon_frame.setLayout(icon_frame_layout)
        icon_title_frame = QFrame(self)
        icon_title_frame_layout = layouts.VerticalLayout(spacing=0,
                                                         margins=(0, 0, 0, 0))
        icon_frame_layout.addWidget(icon_title_frame)
        icon_title_frame.setLayout(icon_title_frame_layout)
        icon_frame2 = QFrame(self)
        icon_frame2_layout = layouts.VerticalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        icon_frame2.setLayout(icon_frame2_layout)
        thumbnail_layout = layouts.HorizontalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        self._thumbnail_frame = QFrame(self)
        thumbnail_frame_layout = layouts.VerticalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        self._thumbnail_frame.setLayout(thumbnail_frame_layout)
        icon_frame_layout.addWidget(icon_frame2)
        icon_frame2_layout.addLayout(thumbnail_layout)
        thumbnail_layout.addWidget(self._thumbnail_frame)
        form_frame = QFrame(self)
        form_frame_layout = layouts.VerticalLayout(spacing=0,
                                                   margins=(0, 0, 0, 0))
        form_frame.setLayout(form_frame_layout)
        main_frame_layout.addWidget(icon_frame)
        main_frame_layout.addWidget(form_frame)

        version_frame = QFrame(self)
        version_frame_layout = layouts.VerticalLayout(spacing=0,
                                                      margins=(0, 0, 0, 0))
        version_frame.setLayout(version_frame_layout)
        self._versions_widget = version.VersionHistoryWidget(parent=self)
        version_frame_layout.addWidget(self._versions_widget)

        self._custom_widget_frame = QFrame(self)
        custom_widget_layout = layouts.VerticalLayout(spacing=0,
                                                      margins=(0, 0, 0, 0))
        self._custom_widget_frame.setLayout(custom_widget_layout)

        self._preview_buttons_frame = QFrame(self)
        preview_buttons_layout = layouts.HorizontalLayout(spacing=2,
                                                          margins=(0, 0, 0, 0))
        self._preview_buttons_frame.setLayout(preview_buttons_layout)
        self._accept_button = buttons.BaseButton('Load', parent=self)
        self._accept_button.setIcon(resources.icon('open'))
        preview_buttons_layout.addStretch()
        preview_buttons_layout.addWidget(self._accept_button)
        preview_buttons_layout.addStretch()

        self._export_btn = buttons.BaseButton('Export', parent=self)
        self._export_btn.setIcon(resources.icon('export'))
        self._import_btn = buttons.BaseButton('Import', parent=self)
        self._import_btn.setIcon(resources.icon('import'))
        self._reference_btn = buttons.BaseButton('Reference', parent=self)
        self._reference_btn.setIcon(resources.icon('reference'))
        for btn in [self._export_btn, self._import_btn, self._reference_btn]:
            btn.setToolTip(btn.text())
        extra_buttons_frame = QFrame(self)
        extra_buttons_layout = layouts.HorizontalLayout(spacing=2,
                                                        margins=(0, 0, 0, 0))
        extra_buttons_frame.setLayout(extra_buttons_layout)
        extra_buttons_layout.addWidget(self._export_btn)
        extra_buttons_layout.addWidget(self._import_btn)
        extra_buttons_layout.addWidget(self._reference_btn)

        group_box = group.GroupBoxWidget('Icon', icon_frame)
        group_box.set_persistent(True)
        group_box.set_checked(True)

        self._version_box = group.GroupBoxWidget('Version', version_frame)
        self._version_box.set_persistent(True)
        self._version_box.set_checked(True)

        self._sequence_widget = sequence.ImageSequenceWidget(self)
        thumbnail_frame_layout.insertWidget(0, self._sequence_widget)

        if os.path.exists(self._item_view.image_sequence_path()):
            self._sequence_widget.set_path(
                self._item_view.image_sequence_path())
        elif os.path.exists(self._item_view.thumbnail_path()):
            self._sequence_widget.set_path(self._item_view.thumbnail_path())

        self._form_widget = formwidget.FormWidget(self)
        self._form_widget.set_schema(self.item().load_schema())
        self._form_widget.set_validator(self.item().load_validator)
        form_frame_layout.addWidget(self._form_widget)

        self.main_layout.addWidget(title_frame)
        self.main_layout.addWidget(group_box)
        self.main_layout.addWidget(main_frame)
        self.main_layout.addWidget(self._version_box)
        self.main_layout.addWidget(version_frame)
        self.main_layout.addWidget(self._custom_widget_frame)
        self.main_layout.addStretch()
        self.main_layout.addWidget(dividers.Divider())
        self.main_layout.addWidget(self._preview_buttons_frame)
        self.main_layout.addWidget(extra_buttons_frame)

    def setup_signals(self):
        self._menu_button.clicked.connect(self._on_show_menu)
        self._accept_button.clicked.connect(self._on_load)
        self._export_btn.clicked.connect(self._on_export)
        self._import_btn.clicked.connect(self._on_import)
        self._reference_btn.clicked.connect(self._on_reference)
        self._item_view.loadValueChanged.connect(self._on_item_value_changed)

    def resizeEvent(self, event):
        """
        Overrides base QWidget resizeEvent function
        :param event: QResizeEvent
        """

        self.update_thumbnail_size()

    def close(self):
        """
        Overrides base QWidget close function to disable script job when its is done
        """

        if self.form_widget():
            self.form_widget().save_persistent_values()

        super(BaseLoadWidget, self).close()

    # ============================================================================================================
    # BASE
    # ============================================================================================================

    def item(self):
        """
        Returns the library item to load
        :return:
        """

        return self._item_view.item

    def item_view(self):
        """
        Returns the library item view to load
        :return: LibraryItem
        """

        return self._item_view

    def form_widget(self):
        """
        Returns form widget instance
        :return: FormWidget
        """

        return self._form_widget

    def set_custom_widget(self, widget):
        """
        Sets custom widget to use when loading items
        :param widget: QQWidget
        """

        self._custom_widget_frame.layout().addWidget(widget)

    def update_thumbnail_size(self):
        """
        Updates the thumbnail button to teh size of the widget
        """

        width = self.width() - 10
        if width > 250:
            width = 250
        size = QSize(width, width)
        self._sequence_widget.setIconSize(size)
        self._sequence_widget.setMaximumSize(size)
        self._thumbnail_frame.setMaximumSize(size)

    # ============================================================================================================
    # INTERNAL
    # ============================================================================================================

    def _update_version_info(self):
        item_view = self.item_view()
        if not item_view or not item_view.library_window():
            return

        library_window = item_view.library_window()
        if not library_window:
            return

        repository_type = library_window.get_repository_type()
        repository_path = library_window.get_repository_path()
        if not repository_type or not repository_path:
            return

        try:
            repository_type = int(repository_type)
        except Exception:
            repository_type = 0

        if repository_type == 0:
            repository_type = None
        elif repository_type == 1:
            repository_type = data_version.GitVersionControl

        self._versions_widget.set_version_control_class(repository_type)
        self._versions_widget.set_repository_path(repository_path)

        # If not valid version control is defined, we hide version control
        valid_version_control = self._versions_widget.set_directory(
            self.item().format_identifier())
        self._versions_widget.setVisible(valid_version_control)
        self._version_box.setVisible(valid_version_control)

    # ============================================================================================================
    # CALLBACKS
    # ============================================================================================================

    def _on_show_menu(self):
        """
        Internal callback function that is called when menu button is clicked byu the user
        :return: QAction
        """

        menu = QMenu(self)
        self._item_view.context_edit_menu(menu)
        point = QCursor.pos()
        point.setX(point.x() + 3)
        point.setY(point.y() + 3)

        return menu.exec_(point)

    def _on_load(self):
        """
        Internal callback function that is called when Load button is pressed by the user
        """

        load_function = self.item().functionality().get('load')
        if not load_function:
            LOGGER.warning(
                'Load functionality is not available for data: "{}"'.format(
                    self.item()))
            return

        library_path = self.item().library.identifier
        if not library_path or not os.path.isfile(library_path):
            LOGGER.warning(
                'Impossible to load data "{}" because its library does not exists: "{}"'
                .format(self.item(), library_path))
            return

        if self._client:
            self._client().load_data(library_path=library_path,
                                     data_path=self.item().format_identifier())
        else:
            load_function()

    def _on_export(self):
        """
        Internal callback function that is called when export button is pressed by the user
        """

        item = self.item()
        if not item:
            return

        library_window = self.item_view().library_window()
        if not library_window:
            return

        base_data.BaseDataItemView.show_export_widget(item.__class__,
                                                      item.format_identifier(),
                                                      library_window)

    def _on_import(self):
        """
        Internal callback function that is called when import button is pressed by the user
        """

        import_function = self.item().functionality().get('import_data')
        if not import_function:
            LOGGER.warning(
                'Import functionality is not available for data: "{}"'.format(
                    self.item()))
            return

        library_path = self.item().library.identifier
        if not library_path or not os.path.isfile(library_path):
            LOGGER.warning(
                'Impossible to load data "{}" because its library does not exists: "{}"'
                .format(self.item(), library_path))
            return

        if self._client:
            self._client().import_data(
                library_path=library_path,
                data_path=self.item().format_identifier())
        else:
            import_function()

    def _on_reference(self):
        """
        Internal callback function that is called when reference button is pressed by the user
        """

        reference_function = self.item().functionality().get('reference_data')
        if not reference_function:
            LOGGER.warning(
                'Reference functionality is not available for data: "{}"'.
                format(self.item()))
            return

        library_path = self.item().library.identifier
        if not library_path or not os.path.isfile(library_path):
            LOGGER.warning(
                'Impossible to load data "{}" because its library does not exists: "{}"'
                .format(self.item(), library_path))
            return

        if self._client:
            self._client().reference_data(
                library_path=library_path,
                data_path=self.item().format_identifier())
        else:
            reference_function()

    def _on_item_value_changed(self, field, value):
        """
        Internal callback function that is called each time an item field value changes
        :param field: str
        :param value: object
        """

        self._form_widget.set_value(field, value)
Пример #22
0
class GroupBoxWidget(base.BaseFrame):

    toggled = Signal(bool)

    def __init__(self,
                 title,
                 widget,
                 persistent=False,
                 settings=None,
                 *args,
                 **kwargs):

        self._title = title
        self._widget = None
        self._persistent = None
        self._settings = settings

        super(GroupBoxWidget, self).__init__(*args, **kwargs)

        if widget:
            self.set_widget(widget)
            # We force the update of the check status to make sure that the wrapped widget visibility is updated
            self.set_checked(self.is_checked())

        self.set_persistent(persistent)

    # ============================================================================================================
    # OVERRIDES
    # ============================================================================================================

    def get_main_layout(self):
        return layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))

    def ui(self):
        super(GroupBoxWidget, self).ui()

        self._title_widget = buttons.BaseButton(self._title, parent=self)
        self._title_widget.setCheckable(True)

        self._on_icon = resources.icon('down_button')
        self._off_icon = resources.icon('right_button')
        self._title_widget.setIcon(self._off_icon)

        self._widget_frame = QFrame(self)
        self._widget_frame.setObjectName('contentsWidget')
        widget_frame_layout = layouts.VerticalLayout(spacing=2,
                                                     margins=(0, 0, 0, 0))
        self._widget_frame.setLayout(widget_frame_layout)

        self.main_layout.addWidget(self._title_widget)
        self.main_layout.addWidget(self._widget_frame)

    def setup_signals(self):
        self._title_widget.toggled.connect(self._on_toggled_title)

    # ============================================================================================================
    # BASE
    # ============================================================================================================

    def is_checked(self):
        """
        Returns whether or not group box is checked
        :return: bool
        """

        return self._title_widget.isChecked()

    def set_checked(self, flag):
        """
        Sets the check statue of the group box
        :param flag: bool
        """

        self._title_widget.setChecked(flag)
        self._title_widget.setIcon(self._on_icon if flag else self._off_icon)
        self._widget_frame.setVisible(flag)
        if self._widget:
            self._widget.setVisible(flag)

    def is_persistent(self):
        """
        Returns whether or not widget state is stored in settings
        :return: bool
        """

        return self._persistent

    def set_persistent(self, flag):
        """
        Sets whether or not widget state is stored in settings
        :param flag: bool
        """

        self._persistent = flag
        self.load_settings()

    def title(self):
        """
        Returns group box title
        :return: str
        """

        return self._title_widget.text()

    def set_widget(self, widget):
        """
        Sets the widget to hide when the user clicks the title
        :param widget: QWidget
        """

        self._widget = widget
        self._widget.setParent(self._widget_frame)
        self._widget_frame.layout().addWidget(self._widget)

    # ============================================================================================================
    # SETTINGS
    # ============================================================================================================

    def load_settings(self):
        """
        Loads widget state from given settings
        """

        if not self._settings or not self._persistent:
            return
        if not self.objectName():
            raise NameError(
                'Impossible to save "{}" widget state because no objectName is defined!'
                .format(self))

        data = {self.objectName(): {'checked': self.is_checked()}}
        self._settings.save(data)

    def save_settings(self):
        """
        Saves current widget state into settings
        """

        if not self._settings or not self._persistent:
            return
        if not self.objectName():
            raise NameError(
                'Impossible to load "{}" widget state because no objectName is defined!'
                .format(self))

        data = self._settings.read()
        data = data.get(self.objectName(), dict())
        if data and isinstance(data, dict):
            checked = data.get('checked', True)
            self.set_checked(checked)

    # ============================================================================================================
    # CALLBACKS
    # ============================================================================================================

    def _on_toggled_title(self, flag):
        """
        Internal callback function that is called each time title group widget is toggled
        :param flag: bool
        """

        self.save_settings()
        self.set_checked(flag)
        self.toggled.emit(flag)
Пример #23
0
class MessageBox(QDialog, object):

    MAX_WIDTH = 320
    MAX_HEIGHT = 220

    @staticmethod
    def input(parent,
              title,
              text,
              input_text='',
              width=None,
              height=None,
              buttons=None,
              header_pixmap=None,
              header_color=None,
              theme_to_apply=None):
        """
        Helper dialog function to get a single text value from the user
        :param parent: QWidget
        :param title: str
        :param text: str
        :param input_text: str
        :param width: int
        :param height: int
        :param buttons: list(QDialogButtonBox.StandardButton)
        :param header_pixmap: QPixmap
        :param header_color: str
        :param theme_to_apply: Theme
        :return: QMessageBox.StandardButton
        """

        buttons = buttons or QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        dialog = create_message_box(parent=parent,
                                    title=title,
                                    text=text,
                                    width=width,
                                    height=height,
                                    buttons=buttons,
                                    header_pixmap=header_pixmap,
                                    header_color=header_color,
                                    enable_input_edit=True,
                                    theme_to_apply=theme_to_apply)
        dialog.set_input_text(input_text)
        dialog.exec_()
        clicked_btn = dialog.clicked_standard_button()

        return dialog.input_text(), clicked_btn

    @staticmethod
    def question(parent,
                 title,
                 text,
                 width=None,
                 height=None,
                 buttons=None,
                 header_pixmap=None,
                 header_color=None,
                 enable_dont_show_checkbox=False,
                 theme_to_apply=None):
        """
        Helper dialog function to get a single text value from the user
        :param parent: QWidget
        :param title: str
        :param text: str
        :param width: int
        :param height: int
        :param buttons: list(QDialogButtonBox.StandardButton)
        :param header_pixmap: QPixmap
        :param header_color: str
        :param enable_dont_show_checkbox: bool
        :param theme_to_apply: Theme
        :return: QDialogButtonBox.StandardButton
        """

        buttons = buttons or QDialogButtonBox.Yes | QDialogButtonBox.No | QDialogButtonBox.Cancel
        clicked_btn = show_message_box(
            parent=parent,
            title=title,
            text=text,
            width=width,
            height=height,
            buttons=buttons,
            header_pixmap=header_pixmap,
            header_color=header_color,
            enable_dont_show_checkbox=enable_dont_show_checkbox,
            theme_to_apply=theme_to_apply)
        return clicked_btn

    @staticmethod
    def warning(parent,
                title,
                text,
                width=None,
                height=None,
                buttons=None,
                header_pixmap=None,
                header_color='rgb(250, 160, 0)',
                enable_dont_show_checkbox=False,
                force=False):
        """
        Helper dialog function to open a warning message box with the given options
        :param parent: QWidget
        :param title: str
        :param text: str
        :param width: int
        :param height: int
        :param buttons: list(QDialogButtonBox.StandardButton)
        :param header_pixmap: QPixmap
        :param header_color: str
        :param enable_dont_show_checkbox: bool
        :param force: bool
        :return: QDialogButtonBox.StandardButton
        """

        buttons = buttons or QDialogButtonBox.Yes | QDialogButtonBox.No
        clicked_btn = show_message_box(
            parent=parent,
            title=title,
            text=text,
            width=width,
            height=height,
            buttons=buttons,
            header_pixmap=header_pixmap,
            header_color=header_color,
            enable_dont_show_checkbox=enable_dont_show_checkbox,
            force=force)
        return clicked_btn

    @staticmethod
    def critical(parent,
                 title,
                 text,
                 width=None,
                 height=None,
                 buttons=None,
                 header_pixmap=None,
                 header_color='rgb(230, 80, 80)'):
        """
        Helper dialog function to open a critical/error message box with the given options
        :param parent: QWidget
        :param title: str
        :param text: str
        :param width: int
        :param height: int
        :param buttons: list(QDialogButtonBox.StandardButton)
        :param header_pixmap: QPixmap
        :param header_color: str
        :return: QDialogButtonBox.StandardButton
        """

        buttons = buttons or QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        clicked_btn = show_message_box(parent=parent,
                                       title=title,
                                       text=text,
                                       width=width,
                                       height=height,
                                       buttons=buttons,
                                       header_pixmap=header_pixmap,
                                       header_color=header_color)
        return clicked_btn

    def __init__(self,
                 name='messageBox',
                 width=None,
                 height=None,
                 enable_input_edit=False,
                 enable_dont_show_checkbox=False,
                 parent=None):

        super(MessageBox, self).__init__(parent=parent)

        self._frame = None
        self._animation = None
        self._dont_show_checkbox = False
        self._clicked_button = None
        self._clicked_standard_button = None

        self.setMinimumWidth(width or self.MAX_WIDTH)
        self.setMinimumHeight(height or self.MAX_HEIGHT)
        self.setObjectName(name)
        self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        # self.setStyleSheet('background-color: rgb(68, 68, 68, 255);')

        parent = self.parent()
        self._frame = None
        if parent and parent != dcc.get_main_window():
            parent.installEventFilter(self)
            self._frame = QFrame(parent)
            self._frame.setStyleSheet(
                'background-color: rgba(25, 25, 25, 150);')
            self._frame.setObjectName('messageBoxFrame')
            self._frame.show()
            self.setParent(self._frame)

        self.main_layout = layouts.VerticalLayout(spacing=0,
                                                  margins=(0, 0, 0, 0))
        self.setLayout(self.main_layout)

        self._header = QFrame(self)
        self._header.setFixedHeight(46)
        self._header.setObjectName('messageBoxHeaderFrame')
        self._header.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        self._icon = label.BaseLabel(parent=self._header)
        self._icon.hide()
        self._icon.setFixedHeight(32)
        self._icon.setFixedHeight(32)
        self._icon.setScaledContents(True)
        self._icon.setAlignment(Qt.AlignTop)
        self._icon.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)

        self._title = label.BaseLabel(parent=self._header)
        self._title.setObjectName('messageBoxHeaderLabel')
        self._title.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        hlayout = layouts.HorizontalLayout(spacing=10, margins=(15, 7, 15, 10))
        hlayout.addWidget(self._icon)
        hlayout.addWidget(self._title)
        self._header.setLayout(hlayout)

        body_layout = layouts.VerticalLayout()
        self._body = QFrame(self)
        self._body.setObjectName('messageBoxBody')
        self._body.setLayout(body_layout)

        self._message = label.BaseLabel(parent=self._body)
        self._message.setWordWrap(True)
        self._message.setMinimumHeight(15)
        self._message.setAlignment(Qt.AlignLeft)
        self._message.setTextInteractionFlags(Qt.TextSelectableByMouse)
        self._message.setSizePolicy(QSizePolicy.Expanding,
                                    QSizePolicy.Expanding)
        body_layout.addWidget(self._message)
        body_layout.setContentsMargins(15, 15, 15, 15)

        if enable_input_edit:
            self._input_edit = lineedit.BaseLineEdit(parent=self._body)
            self._input_edit.setObjectName('messageBoxInputEdit')
            self._input_edit.setMinimumHeight(32)
            self._input_edit.setFocus()
            body_layout.addStretch(1)
            body_layout.addWidget(self._input_edit)
            body_layout.addStretch(10)

        if enable_dont_show_checkbox:
            msg = 'Do not show this message again'
            self._dont_show_checkbox = checkbox.BaseCheckBox(msg,
                                                             parent=self._body)
            body_layout.addStretch(10)
            body_layout.addWidget(self._dont_show_checkbox)
            body_layout.addStretch(2)

        self._button_box = QDialogButtonBox(None, Qt.Horizontal, self)
        self._button_box.clicked.connect(self._on_clicked)
        self._button_box.accepted.connect(self._on_accept)
        self._button_box.rejected.connect(self._on_reject)

        self.main_layout.addWidget(self._header)
        self.main_layout.addWidget(self._body)
        body_layout.addWidget(self._button_box)

        self.updateGeometry()

    def eventFilter(self, object, event):
        """
        Overrides base QDialog eventFilter function
        Updates the geometry when the parnet widget changes size
        :param object: QWidget
        :param event: QEvent
        """

        if event.type() == QEvent.Resize:
            self.updateGeometry()
        return super(MessageBox, self).eventFilter(object, event)

    def showEvent(self, event):
        """
        Overrides base QDialog showEvent function
        Fade in hte dialog on show
        :param event: QEvent
        """

        self.updateGeometry()
        self._fade_in()

    def updateGeometry(self):
        """
        Overrides base QDialog updateGeometry function
        Updates the geometry to be in the center of it's parent
        """

        frame = self._frame
        if frame:
            frame.setGeometry(self._frame.parent().geometry())
            frame.move(0, 0)
            geometry = self.geometry()
            center_point = frame.geometry().center()
            geometry.moveCenter(center_point)
            geometry.setY(geometry.y() - 50)
            self.move(geometry.topLeft())

    def exec_(self):
        """
        Overrides base QDialog exec_ function
        Shows the dialog as a modal dialog
        :return: variant, int or None
        """

        super(MessageBox, self).exec_()
        return self.clicked_index()

    def button_box(self):
        """
        Returns the button box widget for the dialog
        :return: QDialogButtonBox
        """

        return self._button_box

    def header(self):
        """
        Returns the header frame
        :return: QFrame
        """

        return self._header

    def set_header_color(self, color):
        """
        Sets the header color for the message box
        :param color: str
        """

        self.header().setStyleSheet('background-color: {}'.format(color))

    def set_title_text(self, text):
        """
        Sets the title text to be displayed
        :param text: str
        """

        self._title.setText(text)

    def set_text(self, text):
        """
        Sets the text message to be displayed
        :param text: str
        """

        self._message.setText(str(text))

    def input_text(self):
        """
        Returns the text that the user has given in the input edit
        :return: str
        """

        return self._input_edit.text()

    def set_input_text(self, text):
        """
        Sets the input text
        :param text: str
        """

        self._input_edit.setText(text)

    def add_button(self, *args):
        """
        Adds a new upsh button with the given text and roled
        """

        self.button_box().addButton(*args)

    def set_buttons(self, buttons):
        """
        Sets the buttons to be displayed in message box
        :param buttons: QMessageBox.StandardButton
        """

        self.button_box().setStandardButtons(buttons)

    def set_pixmap(self, pixmap):
        """
        Sets the pixmap for the message box
        :param pixmap: QPixmap
        """

        self._icon.setPixmap(pixmap)
        self._icon.show()

    def clicked_button(self):
        """
        Returns the button that was clicked
        :return: variant, QPushButton or None
        """

        return self._clicked_button

    def clicked_index(self):
        """
        Returns the button that was clicked by its index
        :return: variant, int or None
        """

        for i, btn in enumerate(self.button_box().buttons()):
            if btn == self.clicked_button():
                return i

    def clicked_standard_button(self):
        """
        Returns the button that was clicked by the user
        :return: variant, QMessageBox.StandardButton or None
        """

        return self._clicked_standard_button

    def is_dont_show_checkbox_checked(self):
        """
        Returns the checked state of the dont show again checkbox
        :return: bool
        """

        if self._dont_show_checkbox:
            return self._dont_show_checkbox.isChecked()
        else:
            return False

    def _fade_in(self, duration=200):
        """
        Internal function that fade in the dialog using opacity effect
        :param duration: int
        :return: QPropertyAnimation
        """
        if self._frame:
            self._animation = animation.fade_in_widget(self._frame,
                                                       duration=duration)
        return self._animation

    def _fade_out(self, duration=200):
        """
        Internal function that fade out the dialog using opacity effect
        :param duration: int
        :return: QPropertyAnimation
        """
        if self._frame:
            self._animation = animation.fade_out_widget(self._frame,
                                                        duration=duration)
        return self._animation

    def _on_clicked(self, button):
        """
        Internal callback function triggered when the user clicks a button
        :param button: QPushButton
        """

        self._clicked_button = button
        self._clicked_standard_button = self.button_box().standardButton(
            button)

    def _on_accept(self):
        """
        Internal callback function triggered when the DialogButtonBox has been accepted
        """

        anim = self._fade_out()
        if anim:
            anim.finished.connect(self._on_accept_animation_finished)
        else:
            self._on_accept_animation_finished()

    def _on_reject(self):
        """
        Internal callback function triggered when the DialogButtonBox has been rejected
        """

        anim = self._fade_out()
        if anim:
            anim.finished.connect(self._on_reject_animation_finished)
        else:
            self._on_reject_animation_finished()

    def _on_accept_animation_finished(self):
        """
        Internal callback function triggered when the animation has finished on accepted
        """

        parent = self._frame or self
        parent.close()
        self.accept()

    def _on_reject_animation_finished(self):
        parent = self._frame or self
        parent.close()
        self.reject()
Пример #24
0
class IndexedStringsWidget(QWidget):
    """ Holds the list of indexed string attributes """
    def __init__(self, data, parent=None):
        QWidget.__init__(self, parent)
        self.data = data

        vbox = QVBoxLayout()
        self.setLayout(vbox)
        title = QLabel('Indexed Strings')
        vbox.addWidget(title)

        self.frame = QFrame()
        vbox.addWidget(self.frame)
        self.vbox = QVBoxLayout()
        self.frame.setLayout(self.vbox)
        self.frame.setFrameShape(QFrame.Panel)
        self.frame.setFrameShadow(QFrame.Sunken)

        self.table = QTableWidget()
        self.table.horizontalHeader().hide()
        self.vbox.addWidget(self.table)
        self.table.hide()

        self.noStringsLabel = QLabel('<i>No indexed strings</i>')
        self.vbox.addWidget(self.noStringsLabel)

        self.widgets = []
        self.populate()

        self.data.attributeAdded.connect(self.attributeAddedSlot)
        self.data.dataReset.connect(self.dataResetSlot)
        self.data.dirtied.connect(self.dataDirtiedSlot)

    def dataDirtiedSlot(self, dirty):
        """ SLOT when the particle data is dirtied or cleaned."""
        if not dirty:
            for widget in self.widgets:
                widget.drawBorder(False)

    def dataResetSlot(self):
        """ SLOT when particle data is reconstructed """
        self.populate()

    def attributeAddedSlot(self, name): #pylint:disable=W0613
        """ SLOT when an attribute is added to the particle set """
        attr = self.data.attributeInfo(name)
        if attr.type == partio.INDEXEDSTR:
            self.populate()

    def populate(self):
        """ Populates the table of indexed strings """

        self.widgets = []

        # If no widgets, just drop that in
        attrs = []
        for anum in range(self.data.numAttributes()):
            attr = self.data.attributeInfo(anum)
            if attr.type == partio.INDEXEDSTR:
                attrs.append(attr)

        if not attrs:
            self.table.hide()
            self.noStringsLabel.show()
            return

        self.table.show()
        self.noStringsLabel.hide()
        self.table.setColumnCount(1)
        self.table.setRowCount(len(attrs))

        for row, attr in enumerate(attrs):
            item = QTableWidgetItem(attr.name)
            self.table.setVerticalHeaderItem(row, item)
            strings = self.data.indexedStrs(attr)
            table = QTableWidget()
            table.setColumnCount(1)
            table.setRowCount(len(strings))
            table.horizontalHeader().hide()
            table.setVerticalHeaderLabels([str(i) for i in range(len(strings))])
            for i, string in enumerate(strings):
                widget = QLabel(string)
                table.setCellWidget(i, 0, widget)
                self.widgets.append(widget)
            self.table.setCellWidget(row, 0, table)

        self.table.horizontalHeader().setStretchLastSection(False)
        self.table.setTabKeyNavigation(True)
        self.table.horizontalHeader().setSectionsMovable(False)

        self.table.horizontalHeader().resizeSections(QHeaderView.ResizeToContents)
        self.table.verticalHeader().resizeSections(QHeaderView.ResizeToContents)
Пример #25
0
    def ui(self):
        super(PreviewWidget, self).ui()

        title_frame = QFrame(self)
        title_frame_layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        title_frame.setLayout(title_frame_layout)
        title_widget = QWidget(self)
        title_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        title_widget.setLayout(title_layout)
        buttons_layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        title_layout.addLayout(buttons_layout)
        self._title_icon = label.BaseLabel(parent=self)
        self._title_button = label.ElidedLabel(parent=self)
        self._title_button.setText(self.item().name())
        self._menu_button = buttons.BaseButton(parent=self)
        self._menu_button.setIcon(resources.icon('menu_dots'))
        buttons_layout.addWidget(self._title_icon)
        buttons_layout.addStretch()
        buttons_layout.addWidget(self._title_button)
        buttons_layout.addStretch()
        buttons_layout.addWidget(self._menu_button)
        title_frame_layout.addWidget(title_widget)

        item_icon_name = self.item().icon() or 'tpDcc'
        item_icon = resources.icon(item_icon_name)
        if not item_icon:
            item_icon = resources.icon('tpDcc')
        self._title_icon.setPixmap(item_icon.pixmap(QSize(20, 20)))

        icon_title_frame = QFrame(self)
        icon_title_frame_layout = layouts.VerticalLayout(spacing=0, margins=(4, 2, 4, 2))
        icon_title_frame.setLayout(icon_title_frame_layout)

        self._icon_group_frame = QFrame(self)
        icon_group_layout = layouts.HorizontalLayout(spacing=0, margins=(0, 0, 0, 0))
        self._icon_group_frame.setLayout(icon_group_layout)
        self._icon_frame = QFrame(self)
        icon_frame_layout = layouts.VerticalLayout(spacing=0, margins=(4, 2, 4, 2))
        self._icon_frame.setLayout(icon_frame_layout)
        icon_group_layout.addWidget(self._icon_frame)
        icon_group_box_widget = group.GroupBoxWidget('Icon', widget=self._icon_group_frame, parent=self)
        icon_title_frame_layout.addWidget(icon_group_box_widget)

        form_frame = QFrame(self)
        form_frame_layout = layouts.VerticalLayout(spacing=0, margins=(4, 2, 4, 2))
        form_frame.setLayout(form_frame_layout)

        buttons_frame = QFrame(self)
        buttons_frame_layout = layouts.HorizontalLayout(spacing=4, margins=(4, 4, 4, 4))
        buttons_frame.setLayout(buttons_frame_layout)

        self._accept_button = buttons.BaseButton('Load')
        self._accept_button.setIcon(resources.icon('open'))
        self._accept_button.setVisible(False)
        buttons_frame_layout.addWidget(self._accept_button)

        schema = self._item_view.item.load_schema() if self._item_view else None
        if schema:
            self._form_widget = formwidget.FormWidget(self)
            self._form_widget.setObjectName('{}Form'.format(self._item_view.__class__.__name__))
            self._form_widget.set_schema(schema)
            self._form_widget.set_validator(self.validator)
            form_frame_layout.addWidget(self._form_widget)

        self.main_layout.addWidget(title_frame)
        self.main_layout.addWidget(icon_title_frame)
        self.main_layout.addWidget(self._icon_group_frame)
        self.main_layout.addWidget(form_frame)
        self.main_layout.addStretch()
        self.main_layout.addWidget(buttons_frame)
Пример #26
0
class FixedAttributesWidget(QWidget):
    """ A widget for viewing/editing fixed attributes (non-varying) """

    def __init__(self, data, parent=None):
        QWidget.__init__(self, parent)
        self.data = data

        vbox = QVBoxLayout()
        self.setLayout(vbox)
        title = QLabel('Fixed Attributes')
        vbox.addWidget(title)

        self.frame = QFrame()
        vbox.addWidget(self.frame)
        self.vbox = QVBoxLayout()
        self.frame.setLayout(self.vbox)
        self.frame.setFrameShape(QFrame.Panel)
        self.frame.setFrameShadow(QFrame.Sunken)

        self.table = QTableWidget()
        self.table.horizontalHeader().hide()
        self.vbox.addWidget(self.table)
        self.table.hide()

        self.noAttrLabel = QLabel('<i>No fixed attributes</i>')
        self.vbox.addWidget(self.noAttrLabel)


        self.widgets = []
        self.populate()

        self.data.fixedAttributeAdded.connect(self.fixedAttributeAddedSlot)
        self.data.dataReset.connect(self.dataResetSlot)
        self.data.dirtied.connect(self.dataDirtiedSlot)

    def dataDirtiedSlot(self, dirty):
        """ SLOT when the particle data is dirtied or cleaned."""
        if not dirty:
            for widget in self.widgets:
                widget.drawBorder(False)

    def dataResetSlot(self):
        """ SLOT when particle data is reconstructed """
        self.populate()

    def fixedAttributeAddedSlot(self, name): #pylint:disable=W0613
        """ SLOT when a fixed attribute is added to the particle set """
        self.populate()

    def populate(self):
        """ Populates the table of fixed attributes """

        self.widgets = []

        # If no widgets, just drop that in
        numAttrs = self.data.numFixedAttributes()
        if not numAttrs:
            self.table.hide()
            self.noAttrLabel.show()
            return

        self.table.show()
        self.noAttrLabel.hide()
        self.table.setColumnCount(1)
        self.table.setRowCount(numAttrs)
        self.attrs = getAttrs(self.data.numFixedAttributes, self.data.fixedAttributeInfo, True)

        for row, (_, attr) in enumerate(self.attrs):
            item = QTableWidgetItem(attr.name)
            tooltip = '<p><tt>&nbsp;Name: {}<br>&nbsp;Type: {}<br>Count: {}</tt></p>'.\
                      format(attr.name, partio.TypeName(attr.type), attr.count)
            item.setToolTip(tooltip)
            self.table.setVerticalHeaderItem(row, item)
            value = self.data.getFixed(attr)
            widget = getWidget(value, self.data, attr)
            self.table.setCellWidget(row, 0, widget)
            self.widgets.append(widget)
        self.table.horizontalHeader().setStretchLastSection(False)
        self.table.setTabKeyNavigation(True)
        self.table.horizontalHeader().setSectionsMovable(False)

        self.table.horizontalHeader().resizeSections(QHeaderView.ResizeToContents)
        self.table.verticalHeader().resizeSections(QHeaderView.ResizeToContents)
Пример #27
0
class FixedAttributesWidget(QWidget):
    """ A widget for viewing/editing fixed attributes (non-varying) """
    def __init__(self, data, parent=None):
        QWidget.__init__(self, parent)
        self.data = data

        vbox = QVBoxLayout()
        self.setLayout(vbox)
        title = QLabel('Fixed Attributes')
        vbox.addWidget(title)

        self.frame = QFrame()
        vbox.addWidget(self.frame)
        self.vbox = QVBoxLayout()
        self.frame.setLayout(self.vbox)
        self.frame.setFrameShape(QFrame.Panel)
        self.frame.setFrameShadow(QFrame.Sunken)

        self.table = QTableWidget()
        self.table.horizontalHeader().hide()
        self.vbox.addWidget(self.table)
        self.table.hide()

        self.noAttrLabel = QLabel('<i>No fixed attributes</i>')
        self.vbox.addWidget(self.noAttrLabel)

        self.widgets = []
        self.populate()

        self.data.fixedAttributeAdded.connect(self.fixedAttributeAddedSlot)
        self.data.dataReset.connect(self.dataResetSlot)
        self.data.dirtied.connect(self.dataDirtiedSlot)

    def dataDirtiedSlot(self, dirty):
        """ SLOT when the particle data is dirtied or cleaned."""
        if not dirty:
            for widget in self.widgets:
                widget.drawBorder(False)

    def dataResetSlot(self):
        """ SLOT when particle data is reconstructed """
        self.populate()

    def fixedAttributeAddedSlot(self, name):  #pylint:disable=W0613
        """ SLOT when a fixed attribute is added to the particle set """
        self.populate()

    def populate(self):
        """ Populates the table of fixed attributes """

        self.widgets = []

        # If no widgets, just drop that in
        numAttrs = self.data.numFixedAttributes()
        if not numAttrs:
            self.table.hide()
            self.noAttrLabel.show()
            return

        self.table.show()
        self.noAttrLabel.hide()
        self.table.setColumnCount(1)
        self.table.setRowCount(numAttrs)
        self.attrs = getAttrs(self.data.numFixedAttributes,
                              self.data.fixedAttributeInfo, True)

        for row, (_, attr) in enumerate(self.attrs):
            item = QTableWidgetItem(attr.name)
            tooltip = '<p><tt>&nbsp;Name: {}<br>&nbsp;Type: {}<br>Count: {}</tt></p>'.\
                      format(attr.name, partio.TypeName(attr.type), attr.count)
            item.setToolTip(tooltip)
            self.table.setVerticalHeaderItem(row, item)
            value = self.data.getFixed(attr)
            widget = getWidget(value, self.data, attr)
            self.table.setCellWidget(row, 0, widget)
            self.widgets.append(widget)
        self.table.horizontalHeader().setStretchLastSection(False)
        self.table.setTabKeyNavigation(True)
        self.table.horizontalHeader().setSectionsMovable(False)

        self.table.horizontalHeader().resizeSections(
            QHeaderView.ResizeToContents)
        self.table.verticalHeader().resizeSections(
            QHeaderView.ResizeToContents)
Пример #28
0
    def ui(self):
        super(BaseSaveWidget, self).ui()

        self.setWindowTitle('Save Item')

        title_frame = QFrame(self)
        title_frame_layout = layouts.VerticalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        title_frame.setLayout(title_frame_layout)
        title_widget = QFrame(self)
        title_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        title_widget.setLayout(title_layout)
        title_buttons_layout = layouts.HorizontalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        title_layout.addLayout(title_buttons_layout)
        title_icon = label.BaseLabel(parent=self)
        title_button = label.BaseLabel(self.item().menu_name(), parent=self)
        title_button.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Preferred)
        self._menu_button = buttons.BaseButton(parent=self)
        self._menu_button.setIcon(resources.icon('menu_dots'))
        self._menu_button.setVisible(False)  # Hide by default
        title_buttons_layout.addWidget(title_icon)
        title_buttons_layout.addSpacing(5)
        title_buttons_layout.addWidget(title_button)
        title_buttons_layout.addWidget(self._menu_button)
        title_frame_layout.addWidget(title_widget)

        item_icon_name = self.item().icon() or 'tpDcc'
        item_icon = resources.icon(item_icon_name)
        if not item_icon:
            item_icon = resources.icon('tpDcc')
        title_icon.setPixmap(item_icon.pixmap(QSize(20, 20)))

        thumbnail_layout = layouts.HorizontalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        self._thumbnail_frame = QFrame(self)
        thumbnail_frame_layout = layouts.VerticalLayout(spacing=0,
                                                        margins=(0, 2, 0, 2))
        self._thumbnail_frame.setLayout(thumbnail_frame_layout)
        thumbnail_layout.addWidget(self._thumbnail_frame)

        self._options_frame = QFrame(self)
        options_frame_layout = layouts.VerticalLayout(spacing=0,
                                                      margins=(4, 2, 4, 2))
        self._options_frame.setLayout(options_frame_layout)

        preview_buttons_frame = QFrame(self)
        self._preview_buttons_layout = layouts.HorizontalLayout(spacing=0,
                                                                margins=(4, 2,
                                                                         4, 2))
        preview_buttons_frame.setLayout(self._preview_buttons_layout)
        self._save_button = buttons.BaseButton('Save', parent=self)
        self._save_button.setIcon(resources.icon('save'))
        self._cancel_button = buttons.BaseButton('Cancel', parent=self)
        self._cancel_button.setIcon(resources.icon('cancel'))
        self._preview_buttons_layout.addStretch()
        self._preview_buttons_layout.addWidget(self._save_button)
        self._preview_buttons_layout.addStretch()
        self._preview_buttons_layout.addWidget(self._cancel_button)
        self._preview_buttons_layout.addStretch()

        self.main_layout.addWidget(title_frame)
        self.main_layout.addLayout(thumbnail_layout)
        self.main_layout.addWidget(self._options_frame)
        self.main_layout.addWidget(preview_buttons_frame)
Пример #29
0
class LoadWidget(BaseLoadWidget, object):

    HISTORY_WIDGET = history.HistoryFileWidget
    OPTIONS_WIDGET = None

    def __init__(self, item, parent=None):

        self._icon_path = ''
        self._script_job = None
        self._options_widget = None

        super(LoadWidget, self).__init__(item, parent=parent)

        self.load_settings()

        self.create_sequence_widget()
        self.update_thumbnail_size()

    def ui(self):
        super(LoadWidget, self).ui()

        tabs_widget = tabs.BaseTabWidget(parent=self)

        info_widget = QWidget()
        info_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        info_widget.setLayout(info_layout)

        if self.OPTIONS_WIDGET:
            self._options_widget = self.OPTIONS_WIDGET(parent=self)

        title_layout = layouts.HorizontalLayout(spacing=1,
                                                margins=(1, 1, 0, 0))
        self._icon_lbl = label.BaseLabel('', parent=self)
        self._icon_lbl.setMaximumSize(QSize(14, 14))
        self._icon_lbl.setMinimumSize(QSize(14, 14))
        self._icon_lbl.setScaledContents(True)
        self._title_lbl = label.BaseLabel('Title', parent=self)
        title_layout.addWidget(self._icon_lbl)
        title_layout.addWidget(self._title_lbl)

        icon_toggle_box = QFrame()
        icon_toggle_box.setFrameShape(QFrame.NoFrame)
        icon_toggle_box.setFrameShadow(QFrame.Plain)
        icon_toggle_box_lyt = layouts.VerticalLayout(spacing=1,
                                                     margins=(0, 1, 0, 0))
        icon_toggle_box.setLayout(icon_toggle_box_lyt)

        icon_toggle_box_header = QFrame()
        icon_toggle_box_header.setFrameShape(QFrame.NoFrame)
        icon_toggle_box_header.setFrameShadow(QFrame.Plain)
        icon_toggle_box_header_lyt = layouts.VerticalLayout(spacing=0,
                                                            margins=(0, 0, 0,
                                                                     0))
        icon_toggle_box_header.setLayout(icon_toggle_box_header_lyt)

        self._icon_toggle_box_btn = buttons.BaseButton('ICON', parent=self)
        self._icon_toggle_box_btn.setObjectName('iconButton')
        self._icon_toggle_box_btn.setCheckable(True)
        self._icon_toggle_box_btn.setChecked(True)
        icon_toggle_box_header_lyt.addWidget(self._icon_toggle_box_btn)

        self._icon_toggle_box_frame = QFrame()
        self._icon_toggle_box_frame.setFrameShape(QFrame.NoFrame)
        self._icon_toggle_box_frame.setFrameShadow(QFrame.Plain)
        icon_toggle_box_frame_lyt = layouts.VerticalLayout(spacing=1,
                                                           margins=(0, 1, 0,
                                                                    0))
        self._icon_toggle_box_frame.setLayout(icon_toggle_box_frame_lyt)

        thumbnail_layout = layouts.HorizontalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        icon_toggle_box_frame_lyt.addLayout(thumbnail_layout)

        thumbnail_frame_layout = layouts.VerticalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        self._thumbnail_frame = QFrame()
        self._thumbnail_frame.setFrameShape(QFrame.NoFrame)
        self._thumbnail_frame.setFrameShadow(QFrame.Plain)
        self._thumbnail_frame.setLayout(thumbnail_frame_layout)
        thumbnail_layout.addWidget(self._thumbnail_frame)
        self._thumbnail_btn = QToolButton()
        self._thumbnail_btn.setObjectName('thumbnailButton')
        self._thumbnail_btn.setMinimumSize(QSize(0, 0))
        self._thumbnail_btn.setMaximumSize(QSize(150, 150))
        self._thumbnail_btn.setStyleSheet(
            'color: rgb(40, 40, 40);\nborder: 1px solid rgb(0, 0, 0, 0);\nbackground-color: rgb(254, 255, 230, 0);'
        )
        self._thumbnail_btn.setLayoutDirection(Qt.LeftToRight)
        self._thumbnail_btn.setText('Snapshot')
        self._thumbnail_btn.setIcon(resources.icon('thumbnail'))
        thumbnail_frame_layout.addWidget(self._thumbnail_btn)

        icon_toggle_box_lyt.addWidget(icon_toggle_box_header)
        icon_toggle_box_lyt.addWidget(self._icon_toggle_box_frame)

        info_toggle_box = QFrame()
        info_toggle_box.setFrameShape(QFrame.NoFrame)
        info_toggle_box.setFrameShadow(QFrame.Plain)
        info_toggle_box_lyt = layouts.VerticalLayout(spacing=0,
                                                     margins=(0, 0, 0, 0))
        info_toggle_box.setLayout(info_toggle_box_lyt)

        info_toggle_box_header = QFrame()
        info_toggle_box_header.setFrameShape(QFrame.NoFrame)
        info_toggle_box_header.setFrameShadow(QFrame.Plain)
        info_toggle_box_header_lyt = layouts.VerticalLayout(spacing=0,
                                                            margins=(0, 0, 0,
                                                                     0))
        info_toggle_box_header.setLayout(info_toggle_box_header_lyt)

        self._info_toggle_box_btn = buttons.BaseButton('INFO', parent=self)
        self._info_toggle_box_btn.setObjectName('infoButton')
        self._info_toggle_box_btn.setCheckable(True)
        self._info_toggle_box_btn.setChecked(True)
        info_toggle_box_header_lyt.addWidget(self._info_toggle_box_btn)

        self._info_toggle_box_frame = QFrame()
        self._info_toggle_box_frame.setFrameShape(QFrame.NoFrame)
        self._info_toggle_box_frame.setFrameShadow(QFrame.Plain)
        info_toggle_box_frame_lyt = layouts.VerticalLayout(spacing=1,
                                                           margins=(0, 1, 0,
                                                                    0))
        self._info_toggle_box_frame.setLayout(info_toggle_box_frame_lyt)

        self._info_frame = QFrame()
        self._info_frame.setFrameShape(QFrame.NoFrame)
        self._info_frame.setFrameShadow(QFrame.Plain)
        info_frame_lyt = layouts.VerticalLayout(spacing=0,
                                                margins=(0, 0, 0, 0))
        self._info_frame.setLayout(info_frame_lyt)
        info_toggle_box_frame_lyt.addWidget(self._info_frame)

        info_toggle_box_lyt.addWidget(info_toggle_box_header)
        info_toggle_box_lyt.addWidget(self._info_toggle_box_frame)

        version_toggle_box = QFrame()
        version_toggle_box.setFrameShape(QFrame.NoFrame)
        version_toggle_box.setFrameShadow(QFrame.Plain)
        version_toggle_box_lyt = layouts.VerticalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        version_toggle_box.setLayout(version_toggle_box_lyt)

        version_toggle_box_header = QFrame()
        version_toggle_box_header.setFrameShape(QFrame.NoFrame)
        version_toggle_box_header.setFrameShadow(QFrame.Plain)
        version_toggle_box_header_lyt = layouts.VerticalLayout(spacing=0,
                                                               margins=(0, 0,
                                                                        0, 0))
        version_toggle_box_header.setLayout(version_toggle_box_header_lyt)

        self._version_toggle_box_btn = buttons.BaseButton('VERSION',
                                                          parent=self)
        self._version_toggle_box_btn.setObjectName('versionButton')
        self._version_toggle_box_btn.setCheckable(True)
        self._version_toggle_box_btn.setChecked(True)
        version_toggle_box_header_lyt.addWidget(self._version_toggle_box_btn)

        self._version_toggle_box_frame = QFrame()
        self._version_toggle_box_frame.setFrameShape(QFrame.NoFrame)
        self._version_toggle_box_frame.setFrameShadow(QFrame.Plain)
        version_toggle_box_frame_lyt = layouts.VerticalLayout(spacing=1,
                                                              margins=(0, 1, 0,
                                                                       0))
        self._version_toggle_box_frame.setLayout(version_toggle_box_frame_lyt)

        self._version_frame = QFrame()
        self._version_frame.setFrameShape(QFrame.NoFrame)
        self._version_frame.setFrameShadow(QFrame.Plain)
        version_frame_lyt = layouts.VerticalLayout(spacing=0,
                                                   margins=(0, 0, 0, 0))
        self._version_frame.setLayout(version_frame_lyt)
        version_toggle_box_frame_lyt.addWidget(self._version_frame)

        self._history_widget = self.HISTORY_WIDGET()
        version_frame_lyt.addWidget(self._history_widget)

        version_toggle_box_lyt.addWidget(version_toggle_box_header)
        version_toggle_box_lyt.addWidget(self._version_toggle_box_frame)

        preview_buttons_frame = QFrame()
        preview_buttons_frame.setObjectName('previewButtons')
        preview_buttons_frame.setFrameShape(QFrame.NoFrame)
        preview_buttons_frame.setFrameShadow(QFrame.Plain)
        self._preview_buttons_frame_lyt = layouts.VerticalLayout(spacing=0,
                                                                 margins=(2, 2,
                                                                          2,
                                                                          2))
        self._preview_buttons_lyt = layouts.HorizontalLayout(spacing=2,
                                                             margins=(0, 0, 0,
                                                                      0))
        self._load_btn = buttons.BaseButton('Load', parent=self)
        self._load_btn.setObjectName('loadButton')
        self._load_btn.setMinimumSize(QSize(60, 35))
        self._load_btn.setMaximumSize(QSize(125, 35))
        self._preview_buttons_frame_lyt.addStretch()
        self._preview_buttons_frame_lyt.addLayout(self._preview_buttons_lyt)
        self._preview_buttons_frame_lyt.addStretch()
        self._preview_buttons_lyt.addWidget(self._load_btn)
        preview_buttons_frame.setLayout(self._preview_buttons_frame_lyt)

        info_layout.addLayout(title_layout)
        info_layout.addWidget(icon_toggle_box)
        info_layout.addWidget(info_toggle_box)
        info_layout.addWidget(version_toggle_box)

        tabs_widget.addTab(info_widget, 'Info')
        if self._options_widget:
            tabs_widget.addTab(self._options_widget, 'Options')

        self.main_layout.addWidget(tabs_widget)
        self.main_layout.addWidget(dividers.Divider())
        self.main_layout.addWidget(preview_buttons_frame)
        self.main_layout.addItem(
            QSpacerItem(0, 250, QSizePolicy.Preferred, QSizePolicy.Expanding))

    def setup_signals(self):

        self._info_toggle_box_btn.clicked.connect(self.save_settings)
        self._info_toggle_box_btn.toggled[bool].connect(
            self._info_toggle_box_frame.setVisible)
        self._icon_toggle_box_btn.clicked.connect(self.save_settings)
        self._icon_toggle_box_btn.toggled[bool].connect(
            self._icon_toggle_box_frame.setVisible)
        self._version_toggle_box_btn.clicked.connect(self.save_settings)
        self._version_toggle_box_btn.toggled[bool].connect(
            self._version_toggle_box_frame.setVisible)
        self._load_btn.clicked.connect(self.load)

    def resizeEvent(self, event):
        """
        Function that overrides base.BaseWidget function
        :param event: QSizeEvent
        """

        self.update_thumbnail_size()

    def set_item(self, item):
        """
        Sets the library item to load
        :param item: LibraryItem
        """

        super(LoadWidget, self).set_item(item)

        self._title_lbl.setText(item.MenuName)
        self._icon_lbl.setPixmap(QPixmap(item.type_icon_path()))

        info_widget = formwidget.FormWidget(self)
        info_widget.set_schema(item.info())
        self._info_frame.layout().addWidget(info_widget)

        self.refresh()

    def load_btn(self):
        """
        Returns button that loads the data
        :return: QPushButton
        """

        return self._load_btn

    def icon_path(self):
        """
        Returns the icon path to be used for the thumbnail
        :return: str
        """

        return self._icon_path

    def set_icon_path(self, path):
        """
        Sets the icon path to be used for the thumbnail
        :param path: str
        """

        self._icon_path = path
        icon = QIcon(QPixmap(path))
        self.set_icon(icon)
        self.update_thumbnail_size()
        self.item().update()

    def set_icon(self, icon):
        """
        Sets the icon to be shown for the preview
        :param icon: QIcon
        """

        self._thumbnail_btn.setIcon(icon)
        self._thumbnail_btn.setIconSize(QSize(200, 200))
        self._thumbnail_btn.setText('')

    def refresh(self):
        """
        Refreshes load widgetz
        """

        self.update_history()
        self.update_options()

    def update_history(self):
        """
        Updates history version of the current selected item
        """

        if not self._item:
            return

        data_object = self._item.data_object()
        if not data_object:
            return

        self._history_widget.set_directory(data_object.directory)
        self._history_widget.refresh()

    def update_options(self):
        """
        Updates options widget
        """

        if not self._options_widget:
            return

        if not self._item:
            return

        data_object = self._item.data_object()
        if not data_object:
            return

        self._options_widget.set_data_object(data_object)

    def is_editable(self):
        """
        Returns whether the user can edit the item or not
        :return: bool
        """

        item = self.item()
        editable = True

        if item and item.library_window():
            editable = not item.library_window().is_locked()

        return editable

    def create_sequence_widget(self):
        """
        Creates a sequence widget to replace the static thumbnail widget
        """

        self._sequence_widget = widgets.LibraryImageSequenceWidget(self)
        self._sequence_widget.setStyleSheet(self._thumbnail_btn.styleSheet())
        self._sequence_widget.setToolTip(self._thumbnail_btn.toolTip())
        self._thumbnail_frame.layout().insertWidget(0, self._sequence_widget)
        self._thumbnail_btn.hide()
        self._thumbnail_btn = self._sequence_widget
        path = self.item().thumbnail_path()
        if path and os.path.exists(path):
            self.set_icon_path(path)
        if self.item().image_sequence_path():
            self._sequence_widget.set_dirname(
                self.item().image_sequence_path())

    def update_thumbnail_size(self):
        """
        Updates the thumbnail button to the size of the widget
        """

        width = self.width() - 10
        if width > 250:
            width = 250
        size = QSize(width, width)
        self._thumbnail_btn.setIconSize(size)
        self._thumbnail_btn.setMaximumSize(size)
        self._thumbnail_frame.setMaximumSize(size)

    def settings(self):
        """
        Returns the current state of the widget
        :return: dict
        """

        settings = dict()

        settings['iconToggleBoxChecked'] = self._icon_toggle_box_btn.isChecked(
        )
        settings['infoToggleBoxChecked'] = self._info_toggle_box_btn.isChecked(
        )
        settings[
            'versionToggleBoxChecked'] = self._version_toggle_box_btn.isChecked(
            )

        return settings

    def save_settings(self):
        pass

    def load_settings(self):
        pass

    def load(self):
        """
        Loads current item
        """

        if not self.item():
            return

        self.item().load_from_current_options()
Пример #30
0
    def ui(self):
        super(LoadWidget, self).ui()

        tabs_widget = tabs.BaseTabWidget(parent=self)

        info_widget = QWidget()
        info_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        info_widget.setLayout(info_layout)

        if self.OPTIONS_WIDGET:
            self._options_widget = self.OPTIONS_WIDGET(parent=self)

        title_layout = layouts.HorizontalLayout(spacing=1,
                                                margins=(1, 1, 0, 0))
        self._icon_lbl = label.BaseLabel('', parent=self)
        self._icon_lbl.setMaximumSize(QSize(14, 14))
        self._icon_lbl.setMinimumSize(QSize(14, 14))
        self._icon_lbl.setScaledContents(True)
        self._title_lbl = label.BaseLabel('Title', parent=self)
        title_layout.addWidget(self._icon_lbl)
        title_layout.addWidget(self._title_lbl)

        icon_toggle_box = QFrame()
        icon_toggle_box.setFrameShape(QFrame.NoFrame)
        icon_toggle_box.setFrameShadow(QFrame.Plain)
        icon_toggle_box_lyt = layouts.VerticalLayout(spacing=1,
                                                     margins=(0, 1, 0, 0))
        icon_toggle_box.setLayout(icon_toggle_box_lyt)

        icon_toggle_box_header = QFrame()
        icon_toggle_box_header.setFrameShape(QFrame.NoFrame)
        icon_toggle_box_header.setFrameShadow(QFrame.Plain)
        icon_toggle_box_header_lyt = layouts.VerticalLayout(spacing=0,
                                                            margins=(0, 0, 0,
                                                                     0))
        icon_toggle_box_header.setLayout(icon_toggle_box_header_lyt)

        self._icon_toggle_box_btn = buttons.BaseButton('ICON', parent=self)
        self._icon_toggle_box_btn.setObjectName('iconButton')
        self._icon_toggle_box_btn.setCheckable(True)
        self._icon_toggle_box_btn.setChecked(True)
        icon_toggle_box_header_lyt.addWidget(self._icon_toggle_box_btn)

        self._icon_toggle_box_frame = QFrame()
        self._icon_toggle_box_frame.setFrameShape(QFrame.NoFrame)
        self._icon_toggle_box_frame.setFrameShadow(QFrame.Plain)
        icon_toggle_box_frame_lyt = layouts.VerticalLayout(spacing=1,
                                                           margins=(0, 1, 0,
                                                                    0))
        self._icon_toggle_box_frame.setLayout(icon_toggle_box_frame_lyt)

        thumbnail_layout = layouts.HorizontalLayout(spacing=0,
                                                    margins=(0, 0, 0, 0))
        icon_toggle_box_frame_lyt.addLayout(thumbnail_layout)

        thumbnail_frame_layout = layouts.VerticalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        self._thumbnail_frame = QFrame()
        self._thumbnail_frame.setFrameShape(QFrame.NoFrame)
        self._thumbnail_frame.setFrameShadow(QFrame.Plain)
        self._thumbnail_frame.setLayout(thumbnail_frame_layout)
        thumbnail_layout.addWidget(self._thumbnail_frame)
        self._thumbnail_btn = QToolButton()
        self._thumbnail_btn.setObjectName('thumbnailButton')
        self._thumbnail_btn.setMinimumSize(QSize(0, 0))
        self._thumbnail_btn.setMaximumSize(QSize(150, 150))
        self._thumbnail_btn.setStyleSheet(
            'color: rgb(40, 40, 40);\nborder: 1px solid rgb(0, 0, 0, 0);\nbackground-color: rgb(254, 255, 230, 0);'
        )
        self._thumbnail_btn.setLayoutDirection(Qt.LeftToRight)
        self._thumbnail_btn.setText('Snapshot')
        self._thumbnail_btn.setIcon(resources.icon('thumbnail'))
        thumbnail_frame_layout.addWidget(self._thumbnail_btn)

        icon_toggle_box_lyt.addWidget(icon_toggle_box_header)
        icon_toggle_box_lyt.addWidget(self._icon_toggle_box_frame)

        info_toggle_box = QFrame()
        info_toggle_box.setFrameShape(QFrame.NoFrame)
        info_toggle_box.setFrameShadow(QFrame.Plain)
        info_toggle_box_lyt = layouts.VerticalLayout(spacing=0,
                                                     margins=(0, 0, 0, 0))
        info_toggle_box.setLayout(info_toggle_box_lyt)

        info_toggle_box_header = QFrame()
        info_toggle_box_header.setFrameShape(QFrame.NoFrame)
        info_toggle_box_header.setFrameShadow(QFrame.Plain)
        info_toggle_box_header_lyt = layouts.VerticalLayout(spacing=0,
                                                            margins=(0, 0, 0,
                                                                     0))
        info_toggle_box_header.setLayout(info_toggle_box_header_lyt)

        self._info_toggle_box_btn = buttons.BaseButton('INFO', parent=self)
        self._info_toggle_box_btn.setObjectName('infoButton')
        self._info_toggle_box_btn.setCheckable(True)
        self._info_toggle_box_btn.setChecked(True)
        info_toggle_box_header_lyt.addWidget(self._info_toggle_box_btn)

        self._info_toggle_box_frame = QFrame()
        self._info_toggle_box_frame.setFrameShape(QFrame.NoFrame)
        self._info_toggle_box_frame.setFrameShadow(QFrame.Plain)
        info_toggle_box_frame_lyt = layouts.VerticalLayout(spacing=1,
                                                           margins=(0, 1, 0,
                                                                    0))
        self._info_toggle_box_frame.setLayout(info_toggle_box_frame_lyt)

        self._info_frame = QFrame()
        self._info_frame.setFrameShape(QFrame.NoFrame)
        self._info_frame.setFrameShadow(QFrame.Plain)
        info_frame_lyt = layouts.VerticalLayout(spacing=0,
                                                margins=(0, 0, 0, 0))
        self._info_frame.setLayout(info_frame_lyt)
        info_toggle_box_frame_lyt.addWidget(self._info_frame)

        info_toggle_box_lyt.addWidget(info_toggle_box_header)
        info_toggle_box_lyt.addWidget(self._info_toggle_box_frame)

        version_toggle_box = QFrame()
        version_toggle_box.setFrameShape(QFrame.NoFrame)
        version_toggle_box.setFrameShadow(QFrame.Plain)
        version_toggle_box_lyt = layouts.VerticalLayout(spacing=0,
                                                        margins=(0, 0, 0, 0))
        version_toggle_box.setLayout(version_toggle_box_lyt)

        version_toggle_box_header = QFrame()
        version_toggle_box_header.setFrameShape(QFrame.NoFrame)
        version_toggle_box_header.setFrameShadow(QFrame.Plain)
        version_toggle_box_header_lyt = layouts.VerticalLayout(spacing=0,
                                                               margins=(0, 0,
                                                                        0, 0))
        version_toggle_box_header.setLayout(version_toggle_box_header_lyt)

        self._version_toggle_box_btn = buttons.BaseButton('VERSION',
                                                          parent=self)
        self._version_toggle_box_btn.setObjectName('versionButton')
        self._version_toggle_box_btn.setCheckable(True)
        self._version_toggle_box_btn.setChecked(True)
        version_toggle_box_header_lyt.addWidget(self._version_toggle_box_btn)

        self._version_toggle_box_frame = QFrame()
        self._version_toggle_box_frame.setFrameShape(QFrame.NoFrame)
        self._version_toggle_box_frame.setFrameShadow(QFrame.Plain)
        version_toggle_box_frame_lyt = layouts.VerticalLayout(spacing=1,
                                                              margins=(0, 1, 0,
                                                                       0))
        self._version_toggle_box_frame.setLayout(version_toggle_box_frame_lyt)

        self._version_frame = QFrame()
        self._version_frame.setFrameShape(QFrame.NoFrame)
        self._version_frame.setFrameShadow(QFrame.Plain)
        version_frame_lyt = layouts.VerticalLayout(spacing=0,
                                                   margins=(0, 0, 0, 0))
        self._version_frame.setLayout(version_frame_lyt)
        version_toggle_box_frame_lyt.addWidget(self._version_frame)

        self._history_widget = self.HISTORY_WIDGET()
        version_frame_lyt.addWidget(self._history_widget)

        version_toggle_box_lyt.addWidget(version_toggle_box_header)
        version_toggle_box_lyt.addWidget(self._version_toggle_box_frame)

        preview_buttons_frame = QFrame()
        preview_buttons_frame.setObjectName('previewButtons')
        preview_buttons_frame.setFrameShape(QFrame.NoFrame)
        preview_buttons_frame.setFrameShadow(QFrame.Plain)
        self._preview_buttons_frame_lyt = layouts.VerticalLayout(spacing=0,
                                                                 margins=(2, 2,
                                                                          2,
                                                                          2))
        self._preview_buttons_lyt = layouts.HorizontalLayout(spacing=2,
                                                             margins=(0, 0, 0,
                                                                      0))
        self._load_btn = buttons.BaseButton('Load', parent=self)
        self._load_btn.setObjectName('loadButton')
        self._load_btn.setMinimumSize(QSize(60, 35))
        self._load_btn.setMaximumSize(QSize(125, 35))
        self._preview_buttons_frame_lyt.addStretch()
        self._preview_buttons_frame_lyt.addLayout(self._preview_buttons_lyt)
        self._preview_buttons_frame_lyt.addStretch()
        self._preview_buttons_lyt.addWidget(self._load_btn)
        preview_buttons_frame.setLayout(self._preview_buttons_frame_lyt)

        info_layout.addLayout(title_layout)
        info_layout.addWidget(icon_toggle_box)
        info_layout.addWidget(info_toggle_box)
        info_layout.addWidget(version_toggle_box)

        tabs_widget.addTab(info_widget, 'Info')
        if self._options_widget:
            tabs_widget.addTab(self._options_widget, 'Options')

        self.main_layout.addWidget(tabs_widget)
        self.main_layout.addWidget(dividers.Divider())
        self.main_layout.addWidget(preview_buttons_frame)
        self.main_layout.addItem(
            QSpacerItem(0, 250, QSizePolicy.Preferred, QSizePolicy.Expanding))
Пример #31
0
class FormWidget(QFrame, object):

    accepted = Signal(object)
    stateChanged = Signal()
    validated = Signal()

    def __init__(self, *args, **kwargs):
        super(FormWidget, self).__init__(*args, **kwargs)

        self._schema = dict()
        self._widgets = list()
        self._validator = None

        main_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        self.setLayout(main_layout)

        self._fields_frame = QFrame(self)
        self._fields_frame.setObjectName('fieldsFrame')
        options_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0))
        self._fields_frame.setLayout(options_layout)

        self._title_widget = buttons.BaseButton(parent=self)
        self._title_widget.setCheckable(True)
        self._title_widget.setObjectName('titleWidget')
        self._title_widget.toggled.connect(self._on_title_clicked)
        self._title_widget.hide()

        main_layout.addWidget(self._title_widget)
        main_layout.addWidget(self._fields_frame)

    # =================================================================================================================
    # OVERRIDES
    # =================================================================================================================

    def closeEvent(self, event):
        self.save_persistent_values()
        super(FormWidget, self).closeEvent(event)

    # =================================================================================================================
    # BASE
    # =================================================================================================================

    def title_widget(self):
        """
        Returns the title widget
        :return: QWidget
        """

        return self._title_widget

    def set_title(self, title):
        """
        Sets the title text
        :param title: str
        """

        self.title_widget().setText(title)

    def is_expanded(self):
        """
        Returns whether the item is expanded or not
        :return: bool
        """

        return self._title_widget.isChecked()

    def set_expanded(self, flag):
        """
        Expands the options if True, otherwise collapses the options
        :param flag: bool
        """

        with qt_contexts.block_signals(self._title_widget):
            self._title_widget.setChecked(flag)
            self._fields_frame.setVisible(flag)

    def set_title_visible(self, flag):
        """
        Sets whether the title widget is visible or not
        :param flag: bool
        """

        self.title_widget().setVisible(flag)

    def widget(self, name):
        """
        Returns the widget for the given widget name
        :param name: str
        :return: FieldWidget
        """

        for widget in self._widgets:
            if widget.data().get('name') == name:
                return widget

    def value(self, name):
        """
        Returns the value for the given widget name
        :param name: str
        :return: object
        """

        widget = self.widget(name)
        if not widget:
            return None

        return widget.value()

    def set_value(self, name, value):
        """
        Sets the value for the given field name
        :param name: str
        :param value: variant
        """

        widget = self.widget(name)
        widget.set_value(value)

    def values(self):
        """
        Returns all the field values indexed by the field name
        :return: dict
        """

        values = dict()
        for widget in self._widgets:
            name = widget.data().get('name')
            if name:
                values[name] = widget.value()

        return values

    def set_values(self, values):
        """
        Sets the field values for the current form
        :param values: dict
        """

        state = list()
        for name in values:
            state.append({'name': name, 'value': values[name]})

        self._set_state(state)

    def default_values(self):
        """
        Returns all teh default field values indexed by the field name
        :return: dict
        """

        values = dict()
        for widget in self._widgets:
            name = widget.data().get('name')
            if name:
                values[name] = widget.default()

        return values

    def set_data(self, name, data):
        """
        Sets the data for the given field name
        :param name: str
        :param data: dict
        """

        widget = self.widget(name)
        if not widget:
            return
        widget.set_data(data)

    def fields(self):
        """
        Returns fields data for the form
        :return: list(dict)
        """

        options = list()
        for widget in self._widgets:
            options.append(widget.data())

        return options

    def field_widgets(self):
        """
        Returns all field widgets
        :return: list(FieleWidget)
        """

        return self._widgets

    def state(self):
        """
        Returns the current state
        :return: dict
        """

        fields = list()
        for widget in self._widgets:
            fields.append(widget.state())

        state = {
            'fields': fields,
            'expanded': self.is_expanded()
        }

        return state

    def set_state(self, state):
        """
        Sets the current state
        :param state: dict
        """

        expanded = state.get('expanded')
        if expanded is not None:
            self.set_expanded(expanded)

        fields = state.get('fields')
        if fields is not None:
            self._set_state(fields)

        self.validate()

    def schema(self):
        """
        Returns form's schema
        :return: dict
        """

        return self._schema

    def set_schema(self, schema, layout=None, errors_visible=False):
        """
        Sets the schema for the widget
        :param schema: list(dict)
        :param layout: str
        :param errors_visible: str
        """

        self._schema = self._sort_schema(schema)
        if not self._schema:
            return

        for field in schema:
            cls = formfields.FIELD_WIDGET_REGISTRY.get(field.get('type', 'label'))
            if not cls:
                LOGGER.warning('Cannot find widget for {}'.format(field))
                continue
            if layout and not field.get('layout'):
                field['layout'] = layout

            enabled = field.get('enabled', True)
            read_only = field.get('readOnly', False)

            error_visible = field.get('errorVisible')
            field['errorVisible'] = error_visible if error_visible is not None else errors_visible

            widget = cls(data=field, parent=self._fields_frame, form_widget=self)
            data = widget.default_data()
            data.update(field)

            widget.set_data(data)

            value = field.get('value')
            default = field.get('default')
            if value is None and default is not None:
                widget.set_value(default)

            if not enabled or read_only:
                widget.setEnabled(False)

            self._widgets.append(widget)

            callback = partial(self._on_field_changed, widget)
            widget.valueChanged.connect(callback)

            self._fields_frame.layout().addWidget(widget)

        self.load_persistent_values()

    def validator(self):
        """
        Returns the validator for the form
        :return: fn
        """

        return self._validator

    def set_validator(self, validator):
        """
        Sets the validator for the options
        :param validator: fn
        """

        self._validator = validator

    def reset(self):
        """
        Reset all option widget back to the ir default values
        """

        for widget in self._widgets:
            widget.reset()
        self.validate()

    def validate(self, widget=None):
        """
        Validates the current options using the validator
        """

        if not self._validator:
            return

        values = dict()
        for name, value in self.values().items():
            data = self.widget(name).data()
            if data.get('validate', True):
                values[name] = value

        if widget:
            values['fieldChanged'] = widget.name()

        fields = self._validator(**values)
        if fields is not None:
            self._set_state(fields)

        self.validated.emit()

    def errors(self):
        """
        Returns all form errors
        :return: list(str)
        """

        errors = list()
        for widget in self._widgets:
            error = widget.data().get('error')
            if error:
                errors.append(error)

        return errors

    def has_errors(self):
        """
        Returns whether the form contains any error
        :return: bool
        """

        return bool(self.errors())

    def save_persistent_values(self):
        """
        Saves form widget values
        Triggered when the user changes field values
        """

        data = dict()

        for widget in self._widgets:
            name = widget.data().get('name')
            if name and widget.data().get('persistent'):
                key = self.objectName() or 'FormWidget'
                key = widget.data().get('persistentKey', key)
                data.setdefault(key, dict())
                data[key][name] = widget.value()

        for key in data:
            settings.set(key, data[key])

    def load_persistent_values(self):
        """
        Returns the options from the user settings
        :return: dict
        """

        values = dict()
        default_values = self.default_values()

        for field in self.schema():
            name = field.get('name')
            persistent = field.get('persistent')
            if persistent:
                key = self.objectName() or 'FormWidget'
                key = field.get('persistentKey', key)
                value = settings.get(key, dict()).get(name)
            else:
                value = default_values.get(name)

            if value is not None:
                values[name] = value

        self.set_values(values)

    # ============================================================================================================
    # INTERNAL
    # ============================================================================================================

    def _sort_schema(self, schema):
        """
        Internal function that sorts the schema depending on the group order
        :param schema: list(dict)
        :return: list(dict)
        """

        def _key(field):
            return field['order']

        order = 0

        if not schema:
            return

        for i, field in enumerate(schema):
            if field.get('type') == 'group':
                order = field.get('order', order)
            field['order'] = order

        return sorted(schema, key=_key)

    def _set_state(self, fields):
        """
        Internal function that sets fields state
        :param fields: list(dict)
        """

        for widget in self._widgets:
            widget.blockSignals(True)

        try:
            for widget in self._widgets:
                widget.set_error('')
                for field in fields:
                    if field.get('name') == widget.data().get('name'):
                        widget.set_data(field)
        finally:
            for widget in self._widgets:
                widget.blockSignals(False)

        self.stateChanged.emit()

    # ============================================================================================================
    # CALLBACKS
    # ============================================================================================================

    def _on_title_clicked(self, toggle):
        """
        Internal callback function that is triggered when the user clicks in the title widget
        """

        self.set_expanded(toggle)
        self.stateChanged.emit()

    def _on_field_changed(self, widget):
        """
        Internal callback function triggered when the given option widget changes its value
        :param widget: FieldWidget
        """

        self.validate(widget=widget)
Пример #32
0
class SaveWidget(BaseSaveWidget, object):
    def __init__(self, item, settings, temp_path=None, parent=None):

        self._script_job = None
        self._sequence_path = None
        self._icon_path = ''

        super(SaveWidget, self).__init__(item=item,
                                         settings=settings,
                                         temp_path=temp_path,
                                         parent=parent)

        self.create_sequence_widget()
        self.update_thumbnail_size()

        try:
            self._on_selection_changed()
            # self.set_script_job_enabled(True)
        except NameError as e:
            LOGGER.error('{} | {}'.format(e, traceback.format_exc()))

    def ui(self):
        super(SaveWidget, self).ui()

        model_panel_layout = layouts.HorizontalLayout()
        model_panel_layout.setContentsMargins(0, 0, 0, 0)
        model_panel_layout.setSpacing(0)
        thumbnail_layout = layouts.VerticalLayout()
        thumbnail_layout.setContentsMargins(0, 0, 0, 0)
        thumbnail_layout.setSpacing(0)
        self._thumbnail_frame = QFrame()
        self._thumbnail_frame.setMinimumSize(QSize(50, 50))
        self._thumbnail_frame.setMaximumSize(QSize(150, 150))
        self._thumbnail_frame.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self._thumbnail_frame.setFrameShape(QFrame.NoFrame)
        self._thumbnail_frame.setFrameShadow(QFrame.Plain)
        self._thumbnail_frame.setLineWidth(0)
        self._thumbnail_frame.setLayout(thumbnail_layout)
        model_panel_layout.addWidget(self._thumbnail_frame)
        self._thumbnail_btn = QPushButton()
        self._thumbnail_btn.setMinimumSize(QSize(0, 0))
        self._thumbnail_btn.setSizePolicy(QSizePolicy.Expanding,
                                          QSizePolicy.Expanding)
        self._thumbnail_btn.setMaximumSize(QSize(150, 150))
        self._thumbnail_btn.setToolTip('Take snapshot')
        self._thumbnail_btn.setStyleSheet(
            'color: rgb(40, 40, 40);border: 0px solid rgb(0, 0, 0, 150);background-color: rgb(254, 255, 230, 200);'
        )
        self._thumbnail_btn.setIcon(resources.icon('thumbnail'))
        self._thumbnail_btn.setToolTip("""
        Click to capture a thumbnail from the current viewport.\n
        CTRL + Click to show the capture window for better framing
        """)
        thumbnail_layout.addWidget(self._thumbnail_btn)

        self._extra_layout.addLayout(model_panel_layout)

    def setup_signals(self):
        super(SaveWidget, self).setup_signals()
        self._thumbnail_btn.clicked.connect(self._on_thumbnail_capture)

    def resizeEvent(self, event):
        """
        Overrides base QWidget resizeEvent function
        :param event: QResizeEvent
        """

        self.update_thumbnail_size()

    def icon_path(self):
        """
        Returns the icon path to be used for the thumbnail
        :return: str
        """

        return self._icon_path

    def set_icon(self, icon):
        """
        Sets the icon for the create widget thumbnail
        :param icon: QIcon
        """

        self._thumbnail_btn.setIcon(icon)
        self._thumbnail_btn.setIconSize(QSize(200, 200))
        self._thumbnail_btn.setText('')

    def sequence_path(self):
        """
        Returns the playblast path
        :return: str
        """

        return self._sequence_path

    def set_sequence_path(self, path):
        """
        Sets the disk location for the image sequence to be saved
        :param path: str
        """

        self._sequence_path = path
        self._thumbnail_btn.set_dirname(os.path.dirname(path))

    def create_sequence_widget(self):
        """
        Creates a sequence widget to replace the static thumbnail widget
        """

        sequence_widget = widgets.LibraryImageSequenceWidget(self)
        sequence_widget.setObjectName('thumbnailButton')
        sequence_widget.setStyleSheet(self._thumbnail_btn.styleSheet())
        sequence_widget.setToolTip(self._thumbnail_btn.toolTip())

        camera_icon = resources.get('icons', 'camera.svg')
        expand_icon = resources.get('icons', 'expand.svg')
        folder_icon = resources.get('icons', 'folder.svg')

        sequence_widget.addAction(camera_icon, 'Capture new image',
                                  'Capture new image',
                                  self._on_thumbnail_capture)
        sequence_widget.addAction(expand_icon, 'Show Capture window',
                                  'Show Capture window',
                                  self._on_show_capture_window)
        sequence_widget.addAction(folder_icon, 'Load image from disk',
                                  'Load image from disk',
                                  self._on_show_browse_image_dialog)

        sequence_widget.setIcon(resources.icon('thumbnail2'))
        self._thumbnail_frame.layout().insertWidget(0, sequence_widget)
        self._thumbnail_btn.hide()
        self._thumbnail_btn = sequence_widget
        self._thumbnail_btn.clicked.connect(self._on_thumbnail_capture)

    def set_sequence(self, source):
        """
        Sets the sequenced path for the thumbnail widget
        :param source: str
        """

        self.set_thumbnail(source, sequence=True)

    def set_thumbnail(self, source, sequence=False):
        """
        Sets the thumbnail
        :param source: str
        :param sequence: bool
        """

        source = os.path.normpath(source)

        # TODO: Find a way to remove temp folder afteer saving the file
        # filename, extension = os.path.splitext(source)
        # with path_utils.temp_dir() as dir_path:
        # dir_path = path_utils.temp_dir()
        # target = os.path.join(dir_path, 'thumbnail{}'.format(extension))
        # shutil.copyfile(source, target)
        # tpQtLib.logger.debug('Source Thumbnail: {}'.format(source))
        # tpQtLib.logger.debug('Target Thumbnail: {}'.format(target))
        # self._icon_path = target
        # self._thumbnail_btn.set_path(target)

        self._icon_path = source
        self._thumbnail_btn.set_path(source)

        if sequence:
            self.set_sequence_path(source)

    def update_thumbnail_size(self):
        """
        Updates the thumbnail button to teh size of the widget
        """

        width = self.width() - 10
        if width > 250:
            width = 250
        size = QSize(width, width)
        self._thumbnail_btn.setIconSize(size)
        self._thumbnail_btn.setMaximumSize(size)
        self._thumbnail_frame.setMaximumSize(size)

    def show_by_frame_dialog(self):
        """
        Show the by frame dialog
        """

        help_text = """
        To help speed up the playblast you can set the "by frame" to another greather than 1.
        For example if the "by frame" is set to 2 it will playblast every second frame
        """

        options = self._options_widget.values()
        by_frame = options.get('byFrame', 1)
        start_frame, end_frame = options.get('frameRange', [None, None])
        duration = 1
        if start_frame is not None and end_frame is not None:
            duration = end_frame - start_frame
        if duration > 100 and by_frame == 1:
            buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
            result = messagebox.MessageBox.question(
                self.library_window(),
                title='Tip',
                text=help_text,
                buttons=buttons,
                enable_dont_show_checkbox=True)
            if result != QDialogButtonBox.Ok:
                raise Exception('Cancelled by user')

    def show_thumbnail_capture_dialog(self):
        """
        Asks the user if they would like to capture a thumbnail
        :return: int
        """

        buttons = QDialogButtonBox.Yes | QDialogButtonBox.Ignore | QDialogButtonBox.Cancel
        parent = self.item().library_window()
        btn = messagebox.MessageBox.question(
            None,
            'Create a thumbnail',
            'Would you like to capture a thumbnail?',
            buttons=buttons)
        if btn == QDialogButtonBox.Yes:
            self.thumbnail_capture()

        return btn

    def thumbnail_capture(self, show=False):
        """
        Captures a playblast and saves it to the temporal thumbnail path
        :param show: bool
        """

        options = self._options_widget.values()
        start_frame, end_frame = options.get('frameRange', [None, None])
        step = options.get('byFrame', 1)

        if not qtutils.is_control_modifier():
            self.show_by_frame_dialog()

        if not self._temp_path or not os.path.isdir(self._temp_path):
            self._temp_path = tempfile.mkdtemp()
        self._temp_path = os.path.join(self._temp_path, 'thumbnail.jpg')

        try:
            snapshot.SnapshotWindow(path=self._temp_path,
                                    on_save=self._on_thumbnail_captured)
            # thumbnail.ThumbnailCaptureDialog.thumbnail_capture(
            #     path=self._temp_path,
            #     show=show,
            #     start_frame=start_frame,
            #     end_frame=end_frame,
            #     step=step,
            #     clear_cache=False,
            #     captured=self._on_thumbnail_captured
            # )
        except Exception as e:
            messagebox.MessageBox.critical(self.library_window(),
                                           'Error while capturing thumbnail',
                                           str(e))
            LOGGER.error(traceback.format_exc())

    def save(self, path, icon_path, objects=None):
        """
        Saves the item with the given objects to the given disk location path
        :param path: list(str)
        :param icon_path: str
        :param objects: str
        """

        item = self.item()
        options = self._options_widget.values()
        sequence_path = self.sequence_path()
        if sequence_path:
            sequence_path = os.path.dirname(sequence_path)

        item.save(path=path,
                  objects=objects,
                  icon_path=icon_path,
                  sequence_path=sequence_path,
                  **options)

        self.close()

    def _on_selection_changed(self):
        """
        Internal callback functino that is called when DCC selection changes
        """

        if self._options_widget:
            self._options_widget.validate()

    def _on_thumbnail_capture(self):
        self.thumbnail_capture(show=False)

    def _on_thumbnail_captured(self, captured_path):
        """
        Internal callback function that is called when thumbnail is captured
        :param captured_path: str
        """

        self.set_sequence(captured_path)

    def _on_show_capture_window(self):
        """
        Internal callback function that shows the capture window for framing
        """

        self.thumbnail_capture(show=True)

    def _on_show_browse_image_dialog(self):
        """
        Internal callback function that shows a file dialog for choosing an image from disk
        """

        file_dialog = QFileDialog(self,
                                  caption='Open Image',
                                  filter='Image Files (*.png *.jpg)')
        file_dialog.fileSelected.connect(self.set_thumbnail)
        file_dialog.exec_()