Ejemplo n.º 1
0
    def load(self):
        layout = self.layout()

        # Clear
        for btn in self._visButtons:
            layout.removeWidget(btn)
            btn.setVisible(False)
            #TODO sip delete?
        self._visButtons = []

        layers = self._guide.getLayersDepths()
        for i, (depth, layer) in enumerate(layers, start=1):
            btn = QPushButton("    " * depth + layer.name())
            btn.setStyleSheet("Text-align:left")
            btn.setMaximumHeight(20)
            layout.addWidget(btn, i, 0)
            self._visButtons.append(btn)

            for j, option in enumerate(OPTIONS, start=1):
                btn = QPushButton()
                btn.setFixedSize(30, 20)
                kwargs = {x: option == x for x in OPTIONS}
                visible = layer.isVisible(**kwargs)
                self.setButtonColor(btn, visible)

                btn.clicked.connect(
                    partial(self.toggleVisibility, btn, layer, option))

                layout.addWidget(btn, i, j)
                self._visButtons.append(btn)
Ejemplo n.º 2
0
    def ui(self):

        self.color_buttons = list()

        super(BaseColorDialog, self).ui()

        grid_layout = layouts.GridLayout()
        grid_layout.setAlignment(Qt.AlignTop)
        self.main_layout.addLayout(grid_layout)
        color_index = 0
        for i in range(0, 4):
            for j in range(0, 8):
                color_btn = QPushButton()
                color_btn.setMinimumHeight(35)
                color_btn.setMinimumWidth(35)
                self.color_buttons.append(color_btn)
                color_btn.setStyleSheet(
                    'background-color:rgb(%s,%s,%s);' %
                    (self.maya_colors[color_index][0] * 255,
                     self.maya_colors[color_index][1] * 255,
                     self.maya_colors[color_index][2] * 255))
                grid_layout.addWidget(color_btn, i, j)
                color_index += 1
        selected_color_layout = layouts.HorizontalLayout()
        self.main_layout.addLayout(selected_color_layout)
        self.color_slider = QSlider(Qt.Horizontal)
        self.color_slider.setMinimum(0)
        self.color_slider.setMaximum(31)
        self.color_slider.setValue(2)
        self.color_slider.setStyleSheet(
            "QSlider::groove:horizontal {border: 1px solid #999999;height: 25px; /* the groove expands "
            "to the size of the slider by default. by giving it a height, it has a fixed size */background: "
            "qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);margin: 2px 0;}"
            "QSlider::handle:horizontal {background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4,"
            " stop:1 #8f8f8f);border: 1px solid #5c5c5c;width: 10px;margin: -2px 0; /* handle is placed by "
            "default on the contents rect of the groove. Expand outside the groove */border-radius: 1px;}"
        )
        selected_color_layout.addWidget(self.color_slider)

        color_label_layout = layouts.HorizontalLayout(margins=(10, 10, 10, 10))
        self.main_layout.addLayout(color_label_layout)

        self.color_lbl = QLabel()
        self.color_lbl.setStyleSheet(
            "border: 1px solid black; background-color:rgb(0, 0, 0);")
        self.color_lbl.setMinimumWidth(45)
        self.color_lbl.setMaximumWidth(80)
        self.color_lbl.setMinimumHeight(80)
        self.color_lbl.setAlignment(Qt.AlignCenter)
        color_label_layout.addWidget(self.color_lbl)

        bottom_layout = layouts.HorizontalLayout()
        bottom_layout.setAlignment(Qt.AlignRight)
        self.main_layout.addLayout(bottom_layout)

        self.ok_btn = QPushButton('Ok')
        self.cancel_btn = QPushButton('Cancel')
        bottom_layout.addLayout(dividers.DividerLayout())
        bottom_layout.addWidget(self.ok_btn)
        bottom_layout.addWidget(self.cancel_btn)
Ejemplo n.º 3
0
 def generateButtons(self, parent=None):
     """ Generate buttons due to colorDic """
     self.colorButtons = []
     for color in self.colorList:
         button = QPushButton(parent)
         button.setObjectName(color[0])
         button.setStyleSheet('QPushButton { background-color: %s; }' %
                              color[1])
         button.setFixedSize(self.iconWidth / 2, self.iconHeight / 2)
         button.setCheckable(True)
         self.colorButtons.append(button)
Ejemplo n.º 4
0
 def __init__(self, scene, name, parent=None):
     super(UIPinGroup, self).__init__(parent)
     self.setAcceptHoverEvents(True)
     self.borderPen = QtGui.QPen(Colors.DarkGray, 0.5, QtCore.Qt.SolidLine)
     self._scene = scene
     self.layout = QGraphicsLinearLayout(QtCore.Qt.Vertical)
     self.layout.setContentsMargins(0, 0, 0, 0)
     self.layout.setSpacing(NodeDefaults().LAYOUTS_SPACING)
     self.setLayout(self.layout)
     headerBtn = QPushButton(name)
     headerBtn.setStyleSheet(headerBtnStyle)
     headerBtn.setFlat(True)
     headerBtn.setContentsMargins(0, 0, 0, 0)
     headerBtn.setMaximumHeight(10)
     headerBtn.clicked.connect(self.toggleCollapsed)
     self.headerWidget = self._scene.addWidget(headerBtn)
     self.layout.addItem(self.headerWidget)
     self._pins = set()
     self.bCollapsed = False
Ejemplo n.º 5
0
class ExpandablePanel(base.BaseWidget, object):

    def __init__(self, header_text, min_height=30, max_height=1000,
                 show_header_text=True, is_opened=False, parent=None):

        self._header_text = header_text
        self._show_header_text = show_header_text
        self._min_height = min_height
        self._max_height = max_height

        if is_opened:
            self._panel_state = PanelState.OPEN
        else:
            self._panel_state = PanelState.CLOSED
        self._collapse_icon = QIcon()
        self._icon = QPushButton()
        self._icon.setMaximumSize(20, 20)
        self._icon.setIcon(self._collapse_icon)

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

        self.setObjectName('ExpandablePanel')
        self.update_size()
        self.update_icon()

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

        widget_palette = QPalette()
        widget_palette.setColor(QPalette.Background, QColor.fromRgb(60, 60, 60))

        self.setAutoFillBackground(True)
        self.setPalette(widget_palette)

        frame = QFrame()
        frame.setFrameShape(QFrame.StyledPanel)
        frame.setFrameShadow(QFrame.Sunken)
        self.main_layout.addWidget(frame)

        main_layout = layouts.VerticalLayout(spacing=0, margins=(2, 2, 2, 2), parent=frame)
        main_layout.setAlignment(Qt.AlignTop)

        self._header_area = QWidget()
        self._header_area.setMinimumHeight(20)
        self._widget_area = QWidget()
        self._widget_area.setAutoFillBackground(True)
        self._widget_area.setPalette(widget_palette)

        self._header_text_label = dividers.Divider(self._header_text)

        self._widget_layout = layouts.VerticalLayout(spacing=5)
        self._widget_layout.setMargin(5)
        self._widget_area.setLayout(self._widget_layout)

        header_layout = layouts.HorizontalLayout(margins=(0, 0, 0, 0))
        header_layout.addWidget(self._icon)
        header_layout.addWidget(self._header_text_label)
        self._header_area.setLayout(header_layout)

        main_layout.addWidget(self._header_area)
        main_layout.addWidget(self._widget_area)

        self._icon.clicked.connect(self.change_state)

    def update_icon(self):

        if self._panel_state == PanelState.OPEN:
            self._icon.setStyleSheet(
                'QLabel {image: url(:/icons/open_hover_collapsible_panel) no-repeat;} '
                'QLabel:hover {image:url(:/icons/open_hover_collapsible_panel) no-repeat;}')
            self._icon.setToolTip('Close')
            self._widget_area.show()
        else:
            self._icon.setStyleSheet(
                'QLabel {image: url(:/icons/closed_collapsible_panel) no-repeat;} '
                'QLabel:hover {image:url(:/icons/closed_hover_collapsible_panel) no-repeat;}')
            self._icon.setToolTip('Open')
            self._widget_area.hide()

    def update_size(self):
        if self._panel_state == PanelState.OPEN:
            self.setMaximumHeight(self._max_height)
            self.setMinimumHeight(self._min_height)
        else:
            self.setMaximumHeight(self._min_height)
            self.setMinimumHeight(self._min_height)

    def change_state(self):

        if not self._show_header_text:
            self._header_text_label.setVisible(False)

        if self._panel_state == PanelState.OPEN:
            self._panel_state = PanelState.CLOSED
            # self._header_text_label.setText('Closed')
            self._widget_area.hide()
        else:
            self._panel_state = PanelState.OPEN
            # self._header_text_label.setText('Open')
            self._widget_area.show()
        self.update_icon()
        self.update_size()

    def add_widget(self, widget):
        self._widget_layout.addWidget(widget)

    def add_layout(self, layout):
        self._widget_layout.addLayout(layout)
Ejemplo n.º 6
0
class MayaShelf(abstract_shelf.AbstractShelf, object):

    def __init__(self, name='MayaShelf', label_background=(0, 0, 0, 0), label_color=(0.9, 0.9, 0.9),
                 category_icon=None, enable_labels=True):
        super(MayaShelf, self).__init__(name=name, label_background=label_background, label_color=label_color,
                                        category_icon=category_icon, enable_labels=enable_labels)

    @staticmethod
    def add_menu_item(parent, label, command='', icon=''):
        """
        Adds a menu item with the given attributes
        :param parent:
        :param label:
        :param command:
        :param icon:
        :return:
        """

        return maya.cmds.menuItem(parent=parent, label=label, command=command, image=icon or '')

    @staticmethod
    def add_sub_menu(parent, label, icon=None):
        """
        Adds a sub menu item with the given label and icon to the given parent popup menu
        :param parent:
        :param label:
        :param icon:
        :return:
        """

        return maya.cmds.menuItem(parent=parent, label=label, icon=icon or '', subMenu=True)

    def create(self, delete_if_exists=True):
        """
        Creates a new shelf
        """

        if delete_if_exists:
            if gui.shelf_exists(shelf_name=self._name):
                gui.delete_shelf(shelf_name=self._name)
        else:
            assert not gui.shelf_exists(self._name), 'Shelf with name {} already exists!'.format(self._name)

        self._name = gui.create_shelf(name=self._name)

        # ========================================================================================================

        self._category_btn = QPushButton('')
        if self._category_icon:
            self._category_btn.setIcon(self._category_icon)
        self._category_btn.setIconSize(QSize(18, 18))
        self._category_menu = QMenu(self._category_btn)
        self._category_btn.setStyleSheet(
            'QPushButton::menu-indicator {image: url(myindicator.png);'
            'subcontrol-position: right center;subcontrol-origin: padding;left: -2px;}')
        self._category_btn.setMenu(self._category_menu)
        self._category_lbl = QLabel('MAIN')
        self._category_lbl.setAlignment(Qt.AlignCenter)
        font = self._category_lbl.font()
        font.setPointSize(6)
        self._category_lbl.setFont(font)
        menu_ptr = maya.OpenMayaUI.MQtUtil.findControl(self._name)
        menu_widget = qtutils.wrapinstance(menu_ptr, QWidget)
        menu_widget.layout().addWidget(self._category_btn)
        menu_widget.layout().addWidget(self._category_lbl)

        self.add_separator()

    def set_as_active(self):
        """
        Sets this shelf as active shelf in current DCC session
        """

        main_shelf = maya.mel.eval("$_tempVar = $gShelfTopLevel")
        maya.cmds.tabLayout(main_shelf, edit=True, selectTab=self._name)

    def add_button(self, label, tooltip=None, icon='customIcon.png', command=None,
                   double_command=None, command_type='python'):
        """
        Adds a shelf button width the given parameters
        :param label:
        :param tooltip:
        :param icon:
        :param command:
        :param double_command:
        :param command_type:
        :return:
        """

        maya.cmds.setParent(self._name)
        command = command or ''
        double_command = double_command or ''

        if not self._enable_labels:
            label = ''

        return maya.cmds.shelfButton(width=37, height=37, image=icon or '', label=label, command=command,
                                     doubleClickCommand=double_command, annotation=tooltip or '',
                                     imageOverlayLabel=label, overlayLabelBackColor=self._label_background,
                                     overlayLabelColor=self._label_color, sourceType=command_type)

    def add_separator(self):
        """
        Adds a separator to shelf
        :param parent:
        :return:
        """

        maya.cmds.separator(
            parent=self._name, manage=True, visible=True, horizontal=False, style='shelf',
            enableBackground=False, preventOverride=False)

    def build_category(self, shelf_file, category_name):

        self._category_lbl.setText(category_name.upper())

        self.load_category(shelf_file, 'general', clear=True)
        if category_name != 'general':
            self.add_separator()
            self.load_category(shelf_file, category_name, clear=False)

    def build_categories(self, shelf_file, categories):
        """
        Builds all categories given
        :param categories: list<str>, list of categories to build
        """

        self._category_lbl.setText('ALL')

        self.load_category(shelf_file, 'general', clear=True)
        for cat in categories:
            if cat == 'general':
                continue
            self.add_separator()
            self.load_category(shelf_file, cat, clear=False)

    def load_category(self, shelf_file, category_name, clear=True):
        """
        Loads into a shelf all the items of given category name, if exists
        :param category_name: str, name of the category
        """

        if clear:
            self.clear_list()
            # self.add_separator()

        with open(shelf_file) as f:
            shelf_data = json.load(f, object_pairs_hook=OrderedDict)

            for item, item_data in shelf_data.items():
                if item != category_name:
                    continue

                for i in item_data:
                    icon = i.get('icon')
                    command = i.get('command')
                    annotation = i.get('annotation')
                    label = i.get('label')

                    if annotation == 'separator':
                        self.add_separator()
                    else:
                        self.add_button(label=label, command=command, icon=icon, tooltip=annotation)
                return

    def build(self, shelf_file):
        """
        Builds shelf from JSON file
        :param shelf_file: str
        """

        first_item = None

        all_categories = list()

        with open(shelf_file) as f:
            shelf_data = json.load(f, object_pairs_hook=OrderedDict)

            for i, item in enumerate(shelf_data.keys()):
                if i == 0:
                    first_item = item

                category_action = self._category_menu.addAction(item.title())
                category_action.triggered.connect(partial(self.build_category, shelf_file, item))
                all_categories.append(item)

            category_action = self._category_menu.addAction('All')
            category_action.triggered.connect(partial(self.build_categories, shelf_file, all_categories))

        if first_item:
            self.load_category(shelf_file, first_item, clear=False)

    def clear_list(self):
        """
        Clears all the elements of the shelf
        """

        if gui.shelf_exists(shelf_name=self._name):
            menu_items = maya.cmds.shelfLayout(self._name, query=True, childArray=True)
            for item in menu_items:
                try:
                    maya.cmds.deleteUI(item)
                except Exception:
                    pass
Ejemplo n.º 7
0
class WindowDragger(QFrame, object):
    """
    Class to create custom window dragger for Solstice Tools
    """

    DEFAULT_LOGO_ICON_SIZE = 22

    doubleClicked = Signal()

    def __init__(self, window=None, on_close=None):
        super(WindowDragger, self).__init__(window)

        self._window = window
        self._dragging_enabled = True
        self._lock_window_operations = False
        self._mouse_press_pos = None
        self._mouse_move_pos = None
        self._dragging_threshold = 5
        self._minimize_enabled = True
        self._maximize_enabled = True
        self._on_close = on_close

        self.setObjectName('titleFrame')

        self.ui()

    # =================================================================================================================
    # PROPERTIES
    # =================================================================================================================

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

    @property
    def corner_contents_layout(self):
        return self._corner_contents_layout

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

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton and self._dragging_enabled:
            self._mouse_press_pos = event.globalPos()
            self._mouse_move_pos = event.globalPos() - self._window.pos()
        super(WindowDragger, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            global_pos = event.globalPos()
            if self._mouse_press_pos and self._dragging_enabled:
                moved = global_pos - self._mouse_press_pos
                if moved.manhattanLength() > self._dragging_threshold:
                    diff = global_pos - self._mouse_move_pos
                    self._window.move(diff)
                    self._mouse_move_pos = global_pos - self._window.pos()
        super(WindowDragger, self).mouseMoveEvent(event)

    def mouseDoubleClickEvent(self, event):
        if self._lock_window_operations:
            return
        if self._button_maximized.isVisible():
            self._on_maximize_window()
        else:
            self._on_restore_window()
        super(WindowDragger, self).mouseDoubleClickEvent(event)
        self.doubleClicked.emit()

    def mouseReleaseEvent(self, event):
        if self._mouse_press_pos is not None:
            if event.button() == Qt.LeftButton and self._dragging_enabled:
                moved = event.globalPos() - self._mouse_press_pos
                if moved.manhattanLength() > self._dragging_threshold:
                    event.ignore()
                self._mouse_press_pos = None
        super(WindowDragger, self).mouseReleaseEvent(event)

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

    def ui(self):
        self.setFixedHeight(qtutils.dpi_scale(40))

        main_layout = layouts.HorizontalLayout(spacing=5,
                                               margins=(15, 0, 15, 0))
        self.setLayout(main_layout)

        self._logo_button = self._setup_logo_button()
        self._title_text = label.ClippedLabel(text=self._window.windowTitle())
        self._title_text.setObjectName('WindowDraggerLabel')
        self._contents_layout = layouts.HorizontalLayout()
        self._corner_contents_layout = layouts.HorizontalLayout()

        main_layout.addWidget(self._logo_button)
        main_layout.addWidget(self._title_text)
        main_layout.addItem(
            QSpacerItem(25, 0, QSizePolicy.Fixed, QSizePolicy.Fixed))
        main_layout.addLayout(self._contents_layout)
        main_layout.addLayout(self._corner_contents_layout)

        buttons_widget = QWidget()
        self.buttons_layout = layouts.HorizontalLayout(spacing=0,
                                                       margins=(0, 0, 0, 0))
        self.buttons_layout.setAlignment(Qt.AlignRight)
        buttons_widget.setLayout(self.buttons_layout)
        main_layout.addWidget(buttons_widget)

        self._button_minimized = QPushButton()
        self._button_minimized.setIconSize(QSize(25, 25))
        # self._button_minimized.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self._button_minimized.setIcon(
            resources.icon('minimize', theme='window'))
        self._button_minimized.setStyleSheet(
            'QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')
        self._button_maximized = QPushButton()
        self._button_maximized.setIcon(
            resources.icon('maximize', theme='window'))
        # self._button_maximized.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self._button_maximized.setStyleSheet(
            'QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')
        self._button_maximized.setIconSize(QSize(25, 25))
        self._button_restored = QPushButton()
        # self._button_restored.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self._button_restored.setVisible(False)
        self._button_restored.setIcon(resources.icon('restore',
                                                     theme='window'))
        self._button_restored.setStyleSheet(
            'QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')
        self._button_restored.setIconSize(QSize(25, 25))
        self._button_closed = QPushButton()
        # button_closed.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self._button_closed.setIcon(resources.icon('close', theme='window'))
        self._button_closed.setStyleSheet(
            'QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')
        self._button_closed.setIconSize(QSize(25, 25))

        self.buttons_layout.addWidget(self._button_minimized)
        self.buttons_layout.addWidget(self._button_maximized)
        self.buttons_layout.addWidget(self._button_restored)
        self.buttons_layout.addWidget(self._button_closed)

        self._button_maximized.clicked.connect(self._on_maximize_window)
        self._button_minimized.clicked.connect(self._on_minimize_window)
        self._button_restored.clicked.connect(self._on_restore_window)
        self._button_closed.clicked.connect(self._on_close_window)

    def set_icon(self, icon=None, highlight=False):
        """
        Sets the icon of the window dragger
        :param icon: QIcon
        :param highlight: bool
        """

        icon = icon or self._window.windowIcon()
        if not icon or icon.isNull():
            icon = resources.icon('tpDcc')

        size = self.DEFAULT_LOGO_ICON_SIZE

        if highlight:
            self._logo_button.set_icon(
                [icon],
                colors=[None],
                tint_composition=QPainter.CompositionMode_Plus,
                size=size,
                icon_scaling=[1],
                color_offset=0,
                grayscale=True)
        else:
            self._logo_button.set_icon([icon],
                                       colors=None,
                                       size=size,
                                       icon_scaling=[1],
                                       color_offset=0)

        self._logo_button.set_icon_idle(icon)

        # self._lbl_icon.setPixmap(icon.pixmap(icon.actualSize(QSize(24, 24))))

    def set_height(self, value):
        """
        Sets the size of the dragger and updates icon
        :param value: float
        """

        self.setFixedHeight(qtutils.dpi_scale(value))

    def set_title(self, title):
        """
        Sets the title of the window dragger
        :param title: str
        """

        self._title_text.setText(title)

    def set_dragging_enabled(self, flag):
        """
        Sets whether or not drag functionality is enabled
        :param flag: bool
        """

        self._dragging_enabled = flag

    def set_minimize_enabled(self, flag):
        """
        Sets whether dragger shows minimize button or not
        :param flag: bool
        """

        self._minimize_enabled = flag
        self._button_minimized.setVisible(flag)

    def set_maximized_enabled(self, flag):
        """
        Sets whether dragger shows maximize button or not
        :param flag: bool
        """

        self._maximize_enabled = flag
        self._button_maximized.setVisible(flag)

    def show_logo(self):
        """
        Shows window logo
        """

        self._logo_button.setVisible(True)

    def hide_logo(self):
        """
        Hides window logo
        """

        self._logo_button.setVisible(False)

    def set_window_buttons_state(self, state, show_close_button=False):
        """
        Sets the state of the dragger buttons
        :param state: bool
        :param show_close_button: bool
        """

        self._lock_window_operations = not state
        self._button_closed.setEnabled(state or show_close_button)
        self._button_closed.setVisible(state or show_close_button)

        if self._maximize_enabled:
            self._button_maximized.setEnabled(state)
            self._button_maximized.setVisible(state)
        else:
            self._button_maximized.setEnabled(False)
            self._button_maximized.setVisible(False)

        if self._minimize_enabled:
            self._button_minimized.setEnabled(state)
            self._button_minimized.setVisible(state)
        else:
            self._button_minimized.setEnabled(False)
            self._button_minimized.setVisible(False)

        if not state:
            self._button_restored.setEnabled(state)
            self._button_restored.setVisible(state)
        else:
            if self.isMaximized():
                self._button_restored.setEnabled(state)
                self._button_restored.setVisible(state)

    def set_frameless_enabled(self, frameless=False):
        """
        Enables/Disables frameless mode or OS system default
        :param frameless: bool
        """

        from tpDcc.managers import tools

        tool_inst = tools.ToolsManager().get_tool_by_plugin_instance(
            self._window)
        if not tool_inst:
            return

        offset = QPoint()

        if self._window.docked():
            rect = self._window.rect()
            pos = self._window.mapToGlobal(QPoint(-10, -10))
            rect.setWidth(rect.width() + 21)
            self._window.close()
        else:
            rect = self.window().rect()
            pos = self.window().pos()
            offset = QPoint(3, 15)
            self.window().close()

        tool_inst._launch(launch_frameless=frameless)

        new_tool = tool_inst.latest_tool()

        QTimer.singleShot(
            0,
            lambda: new_tool.window().setGeometry(pos.x() + offset.x(),
                                                  pos.y() + offset.y(),
                                                  rect.width(), rect.height()))
        new_tool.framelessChanged.emit(frameless)
        QApplication.processEvents()

        return new_tool

    def _setup_logo_button(self):
        """
        Internal function that setup window dragger button logo
        :return: IconMenuButton
        """

        from tpDcc.libs.qt.widgets import buttons
        logo_button = buttons.IconMenuButton(parent=self)
        logo_button.setIconSize(QSize(24, 24))
        logo_button.setFixedSize(QSize(30, 30))
        self._toggle_frameless = logo_button.addAction(
            'Toggle Frameless Mode',
            connect=self._on_toggle_frameless_mode,
            checkable=True)
        self._toggle_frameless.setChecked(self._window.is_frameless())
        logo_button.set_menu_align(Qt.AlignLeft)

        return logo_button

    def _on_toggle_frameless_mode(self, action):
        """
        Internal callback function that is called when switch frameless mode button is pressed by user
        :param flag: bool
        """

        self.set_frameless_enabled(action.isChecked())

    def _on_maximize_window(self):
        """
        Internal callback function that is called when the user clicks on maximize button
        """

        self._button_restored.setVisible(True)
        self._button_maximized.setVisible(False)
        self._window.setWindowState(Qt.WindowMaximized)

    def _on_minimize_window(self):
        """
        Internal callback function that is called when the user clicks on minimize button
        """

        self._window.setWindowState(Qt.WindowMinimized)

    def _on_restore_window(self):
        """
        Internal callback function that is called when the user clicks on restore button
        """

        self._button_restored.setVisible(False)
        self._button_maximized.setVisible(True)
        self._window.setWindowState(Qt.WindowNoState)

    def _on_close_window(self):
        """
        Internal callback function that is called when the user clicks on close button
        """

        from tpDcc.managers import tools

        closed = False
        if hasattr(self._window, 'WindowId'):
            closed = tools.ToolsManager().close_tool(self._window.WindowId,
                                                     force=False)

        if not closed:
            if hasattr(self._window, 'docked'):
                if self._window.docked():
                    self._window.fade_close()
                else:
                    self.window().fade_close()
            else:
                self._window.fade_close()
Ejemplo n.º 8
0
class WindowStatusBar(statusbar.StatusWidget, object):
    def __init__(self, parent=None):
        super(WindowStatusBar, self).__init__(parent)

        self._info_url = None
        self._tool = None

        self.setFixedHeight(25)
        self._info_btn = QPushButton()
        self._info_btn.setIconSize(QSize(25, 25))
        self._info_btn.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self._info_btn.setIcon(resources.icon('info1'))
        self._info_btn.setStyleSheet('QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')

        self._bug_btn = QPushButton()
        self._bug_btn.setIconSize(QSize(25, 25))
        self._bug_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self._bug_btn.setIcon(resources.icon('bug'))
        self._bug_btn.setStyleSheet('QWidget {background-color: rgba(255, 255, 255, 0); border:0px;}')

        self.main_layout.insertWidget(0, self._info_btn)
        self.main_layout.insertWidget(1, self._bug_btn)

        self._info_btn.clicked.connect(self._on_open_url)
        self._bug_btn.clicked.connect(self._on_send_bug)

    def set_info_url(self, url):
        """
        Sets the URL used to open tool info documentation web
        :param url: str
        """

        self._info_url = url

    def set_tool(self, tool):
        """

        :param tool:
        :return:
        """

        self._tool = tool

    def has_url(self):
        """
        Returns whether the URL documentation web is set or not
        :return: bool
        """

        if self._info_url:
            return True

        return False

    def has_tool(self):
        """
        Returns whether window has a tool attached or not
        :return: bool
        """

        if self._tool:
            return True

        return False

    def show_info(self):
        """
        Shows the info button of the status bar
        """

        self._info_btn.setVisible(True)

    def hide_info(self):
        """
        Hides the info button of the status bar
        """

        self._info_btn.setVisible(False)

    def show_bug(self):
        self._bug_btn.setVisible(True)

    def hide_bug(self):
        self._bug_btn.setVisible(False)

    def open_info_url(self):
        """
        Opens tool documentation URL in user web browser
        """

        if not self._project:
            return False

        if self._info_url:
            webbrowser.open_new_tab(self._info_url)

    def _on_send_bug(self):

        if not self._project:
            return False

        # tools.ToolsManager().run_tool(self._project, 'bugtracker', extra_args={'tool': self._tool})

    def _on_open_url(self):
        """
        Internal callback function that is called when the user presses the info icon button
        :return:
        """

        self.open_info_url()
Ejemplo n.º 9
0
class PenSetWidget(QWidget):

    penSizeTrigger = Signal(int)
    penColorTrigger = Signal(str)
    fontChangeTrigger = Signal(QFont)

    def __init__(self, parent=None):
        super(PenSetWidget, self).__init__(parent)

        self.paddingX = 5
        self.paddingY = 2
        self.iconWidth = self.iconHeight = 24
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        self.setWindowFlags(Qt.ToolTip)

        self.initWindows()

        self.prevSizeButton = self.penSize1
        self.penSize1.setChecked(True)
        self.presentColor.setStyleSheet(
            'QPushButton { background-color: %s; }' % PENCOLOR)

    def generateButtons(self, parent=None):
        """ Generate buttons due to colorDic """
        self.colorButtons = []
        for color in self.colorList:
            button = QPushButton(parent)
            button.setObjectName(color[0])
            button.setStyleSheet('QPushButton { background-color: %s; }' %
                                 color[1])
            button.setFixedSize(self.iconWidth / 2, self.iconHeight / 2)
            button.setCheckable(True)
            self.colorButtons.append(button)

    def initWindows(self):
        self.mainLayout = QHBoxLayout()
        self.setLayout(self.mainLayout)
        self.mainLayout.setSpacing(0)
        self.mainLayout.setContentsMargins(5, 2, 5, 2)

        self.initPenSizeButtons()
        self.initFontWidget()
        self.initPenColorButtons()

        self.separator = QFrame(self)
        self.separator.setFrameShape(QFrame.VLine)
        self.separator.setFrameShadow(QFrame.Sunken)

        self.mainLayout.addWidget(self.penSize)
        self.mainLayout.addWidget(self.changeFontButton)
        self.mainLayout.addWidget(self.separator)

        self.mainLayout.addWidget(self.colorSet)

    def initPenSizeButtons(self):
        self.penSize = QWidget(self)
        self.penSizeLayout = QHBoxLayout()
        self.penSize.setLayout(self.penSizeLayout)
        # adjust pen size
        self.penSize1 = QPushButton(self.penSize)
        self.penSize1.setIcon(QIcon(":/resource/icon/pensize1.png"))
        self.penSize1.setObjectName('1')
        self.penSize1.setFixedSize(self.iconWidth, self.iconHeight)
        self.penSize1.setCheckable(True)

        self.penSize2 = QPushButton(self.penSize)
        self.penSize2.setIcon(QIcon(":/resource/icon/pensize2.png"))
        self.penSize2.setObjectName('2')
        self.penSize2.setFixedSize(self.iconWidth, self.iconHeight)
        self.penSize2.setCheckable(True)

        self.penSize3 = QPushButton(self.penSize)
        self.penSize3.setIcon(QIcon(":/resource/icon/pensize3.png"))
        self.penSize3.setObjectName('3')
        self.penSize3.setFixedSize(self.iconWidth, self.iconHeight)
        self.penSize3.setCheckable(True)

        self.sizeButtonGroup = QButtonGroup(self.penSize)
        self.sizeButtonGroup.addButton(self.penSize1)
        self.sizeButtonGroup.addButton(self.penSize2)
        self.sizeButtonGroup.addButton(self.penSize3)
        self.sizeButtonGroup.buttonClicked.connect(self.sizeButtonToggled)

        self.penSizeLayout.addWidget(self.penSize1)
        self.penSizeLayout.addWidget(self.penSize2)
        self.penSizeLayout.addWidget(self.penSize3)

        self.penSizeLayout.setSpacing(5)
        self.penSizeLayout.setContentsMargins(0, 0, 0, 0)

    def initPenColorButtons(self):
        self.colorSet = QWidget(self)
        self.colorLayout = QHBoxLayout()
        self.colorLayout.setSpacing(5)
        self.colorLayout.setContentsMargins(5, 0, 5, 0)
        self.colorSet.setLayout(self.colorLayout)

        self.presentColor = QPushButton(self.colorSet)
        self.presentColor.setFixedSize(self.iconWidth, self.iconHeight)
        self.presentColor.setEnabled(False)

        # adjust pen color

        self.colorPick = QWidget(self.colorSet)
        self.colorGrid = QGridLayout()
        self.colorGrid.setSpacing(0)
        self.colorGrid.setContentsMargins(5, 0, 5, 0)
        self.colorPick.setLayout(self.colorGrid)

        self.colorList = [('white', '#ffffff'), ('red', '#ff0000'),
                          ('green', '#00ff00'), ('blue', '#0000ff'),
                          ('cyan', '#00ffff'), ('magenta', '#ff00ff'),
                          ('yellow', '#ffff00'), ('gray', '#a0a0a4'),
                          ('black', '#000000'), ('darkRed', '#800000'),
                          ('darkGreen', '#008000'), ('darkBlue', '#000080'),
                          ('darkCyan', '#008080'), ('darkMagenta', '#800080'),
                          ('darkYellow', '#808000'), ('darkGray', '#808080')]

        self.generateButtons()

        self.colorButtonGroup = QButtonGroup(self)
        for button in self.colorButtons:
            self.colorButtonGroup.addButton(button)
        self.colorButtonGroup.buttonClicked.connect(self.colorButtonToggled)

        # set the layout
        tmp = 0
        for x in range(0, 2):
            for y in range(0, int(len(self.colorList) / 2)):
                self.colorGrid.addWidget(self.colorButtons[tmp], x, y)
                tmp += 1

        self.colorGrid.setSpacing(0)
        self.colorGrid.setContentsMargins(0, 0, 0, 0)

        self.colorLayout.addWidget(self.presentColor)
        self.colorLayout.addWidget(self.colorPick)

    def initFontWidget(self):
        self.fontDialog = QFontDialog()
        self.changeFontButton = QPushButton(self)
        self.fontDialog.setCurrentFont(QFont('Sans serif'))
        self.changeFontButton.setText('{0} {1}'.format(
            self.fontDialog.currentFont().family(),
            self.fontDialog.currentFont().pointSize()))
        self.changeFontButton.clicked.connect(self.fontButtonClicked)

    def showFontWidget(self):
        self.changeFontButton.show()
        self.penSize1.hide()
        self.penSize2.hide()
        self.penSize3.hide()

    def showPenWidget(self):
        self.changeFontButton.hide()
        self.penSize1.show()
        self.penSize2.show()
        self.penSize3.show()

    # slots
    def colorButtonToggled(self, button):
        self.presentColor.setStyleSheet(
            'QPushButton { background-color: %s; }' % button.objectName())
        self.penColorTrigger.emit(button.objectName())

    def sizeButtonToggled(self, button):
        self.penSizeTrigger.emit(int(button.objectName()) * 2)

    def fontButtonClicked(self):
        ok = True
        font = QFontDialog.getFont(self)
        if font[1]:
            self.changeFontButton.setText('{0} {1}'.format(
                font[0].family(), font[0].pointSize()))
            self.fontChangeTrigger.emit(font[0])
Ejemplo n.º 10
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_()