Пример #1
0
class MSequenceFile(QWidget, MFieldMixin):
    '''
    这个类必须依赖 DayuPath
    props:
        path: six.string_types
        sequence: bool
    '''
    sig_is_sequence_changed = Signal(bool)

    def __init__(self, size=None, parent=None):
        super(MSequenceFile, self).__init__(parent)
        self.sequence_obj = None
        size = size or dayu_theme.small
        self._file_label = MLineEdit()
        self._file_label.set_dayu_size(size)
        self._file_label.setReadOnly(True)
        self._is_sequence_check_box = MCheckBox(self.tr('Sequence'))
        self._is_sequence_check_box.toggled.connect(
            functools.partial(self.setProperty, 'sequence'))
        self._is_sequence_check_box.toggled.connect(
            self.sig_is_sequence_changed)

        self._info_label = MLabel().secondary()
        self._error_label = MLabel().secondary()
        self._error_label.setProperty('error', True)
        self._error_label.setMinimumWidth(100)
        self._error_label.set_elide_mode(Qt.ElideMiddle)

        seq_lay = QHBoxLayout()
        seq_lay.addWidget(self._is_sequence_check_box)
        seq_lay.addWidget(self._info_label)
        seq_lay.addWidget(self._error_label)
        seq_lay.setStretchFactor(self._is_sequence_check_box, 0)
        seq_lay.setStretchFactor(self._info_label, 0)
        seq_lay.setStretchFactor(self._error_label, 100)

        self._main_lay = QVBoxLayout()
        self._main_lay.setContentsMargins(0, 0, 0, 0)
        self._main_lay.addWidget(self._file_label)
        self._main_lay.addLayout(seq_lay)
        self.setLayout(self._main_lay)
        self.set_sequence(True)

    def _set_path(self, value):
        path = DayuPath(value)
        for seq_obj in path.scan():
            self.sequence_obj = seq_obj
        self._update_info()

    def set_path(self, value):
        self.setProperty('path', value)

    def set_sequence(self, value):
        assert isinstance(value, bool)
        self.setProperty('sequence', value)

    def _set_sequence(self, value):
        if value != self._is_sequence_check_box.isChecked():
            # 更新来自代码
            self._is_sequence_check_box.setChecked(value)
            self.sig_is_sequence_changed.emit(value)
        self._update_info()

    def _update_info(self):
        self._file_label.setProperty(
            'text', self.sequence_obj
            if self.property('sequence') else self.property('path'))
        if self.sequence_obj:
            self._info_label.setText(u'Format: {ext}  '
                                     u'Total: {count}  '
                                     u'Range: {start}-{end}'.format(
                                         ext=self.sequence_obj.ext,
                                         count=len(self.sequence_obj.frames),
                                         start=self.sequence_obj.frames[0]
                                         if self.sequence_obj.frames else '/',
                                         end=self.sequence_obj.frames[-1]
                                         if self.sequence_obj.frames else '/'))
            error_info = u'Missing: {}'.format(
                self.sequence_obj.missing) if self.sequence_obj.missing else ''
            self._error_label.setText(error_info)
            self._error_label.setToolTip(error_info)
        self._info_label.setVisible(self.property('sequence'))
        self._error_label.setVisible(self.property('sequence'))
Пример #2
0
class MMeta(QWidget):
    def __init__(self,
                 cover=None,
                 avatar=None,
                 title=None,
                 description=None,
                 extra=False,
                 parent=None):
        super(MMeta, self).__init__(parent)
        self.setAttribute(Qt.WA_StyledBackground)
        self._cover_label = QLabel()
        self._avatar = MAvatar()
        self._title_label = MLabel().h4()
        self._description_label = MLabel().secondary()
        self._description_label.setWordWrap(True)
        self._description_label.set_elide_mode(Qt.ElideRight)
        self._title_layout = QHBoxLayout()
        self._title_layout.addWidget(self._title_label)
        self._title_layout.addStretch()
        self._extra_button = MToolButton(
            parent=self).icon_only().svg('more.svg')
        self._title_layout.addWidget(self._extra_button)
        self._extra_button.setVisible(extra)

        content_lay = QFormLayout()
        content_lay.setContentsMargins(5, 5, 5, 5)
        content_lay.addRow(self._avatar, self._title_layout)
        content_lay.addRow(self._description_label)

        self._button_layout = QHBoxLayout()

        main_lay = QVBoxLayout()
        main_lay.setSpacing(0)
        main_lay.setContentsMargins(1, 1, 1, 1)
        main_lay.addWidget(self._cover_label)
        main_lay.addLayout(content_lay)
        main_lay.addLayout(self._button_layout)
        main_lay.addStretch()
        self.setLayout(main_lay)
        self._cover_label.setFixedSize(QSize(200, 200))
        # self.setFixedWidth(200)

    def get_more_button(self):
        return self._extra_button

    def setup_data(self, data_dict):
        if data_dict.get('title'):
            self._title_label.setText(data_dict.get('title'))
            self._title_label.setVisible(True)
        else:
            self._title_label.setVisible(False)

        if data_dict.get('description'):
            self._description_label.setText(data_dict.get('description'))
            self._description_label.setVisible(True)
        else:
            self._description_label.setVisible(False)

        if data_dict.get('avatar'):
            self._avatar.set_dayu_image(data_dict.get('avatar'))
            self._avatar.setVisible(True)
        else:
            self._avatar.setVisible(False)

        if data_dict.get('cover'):
            fixed_height = self._cover_label.width()
            self._cover_label.setPixmap(
                data_dict.get('cover').scaledToWidth(fixed_height,
                                                     Qt.SmoothTransformation))
            self._cover_label.setVisible(True)
        else:
            self._cover_label.setVisible(False)
Пример #3
0
class MProgressCircle(QProgressBar):
    """
    MProgressCircle: Display the current progress of an operation flow.
    When you need to display the completion percentage of an operation.

    Property:
        dayu_width: int
        dayu_color: str
    """

    def __init__(self, dashboard=False, parent=None):
        super(MProgressCircle, self).__init__(parent)
        self._main_lay = QHBoxLayout()
        self._default_label = MLabel().h3()
        self._default_label.setAlignment(Qt.AlignCenter)
        self._main_lay.addWidget(self._default_label)
        self.setLayout(self._main_lay)
        self._color = None
        self._width = None

        self._start_angle = 90 * 16
        self._max_delta_angle = 360 * 16
        self._height_factor = 1.0
        self._width_factor = 1.0
        if dashboard:
            self._start_angle = 225 * 16
            self._max_delta_angle = 270 * 16
            self._height_factor = (2 + pow(2, 0.5)) / 4 + 0.03

        self.set_dayu_width(120)
        self.set_dayu_color(dayu_theme.primary_color)

    def set_widget(self, widget):
        """
        Set a custom widget to show on the circle's inner center
         and replace the default percent label
        :param widget: QWidget
        :return: None
        """
        self.setTextVisible(False)
        self._main_lay.addWidget(widget)

    def get_dayu_width(self):
        """
        Get current circle fixed width
        :return: int
        """
        return self._width

    def set_dayu_width(self, value):
        """
        Set current circle fixed width
        :param value: int
        :return: None
        """
        self._width = value
        self.setFixedSize(QSize(self._width * self._width_factor,
                                self._width * self._height_factor))

    def get_dayu_color(self):
        """
        Get current circle foreground color
        :return: str
        """
        return self._color

    def set_dayu_color(self, value):
        """
        Set current circle's foreground color
        :param value: str
        :return:
        """
        self._color = value
        self.update()

    dayu_color = Property(str, get_dayu_color, set_dayu_color)
    dayu_width = Property(int, get_dayu_width, set_dayu_width)

    def paintEvent(self, event):
        """Override QProgressBar's paintEvent."""
        if self.text() != self._default_label.text():
            self._default_label.setText(self.text())
        if self.isTextVisible() != self._default_label.isVisible():
            self._default_label.setVisible(self.isTextVisible())

        percent = utils.get_percent(self.value(), self.minimum(), self.maximum())
        total_width = self.get_dayu_width()
        pen_width = int(3 * total_width / 50.0)
        radius = total_width - pen_width - 1

        painter = QPainter(self)
        painter.setRenderHints(QPainter.Antialiasing)

        # draw background circle
        pen_background = QPen()
        pen_background.setWidth(pen_width)
        pen_background.setColor(dayu_theme.background_selected_color)
        pen_background.setCapStyle(Qt.RoundCap)
        painter.setPen(pen_background)
        painter.drawArc(pen_width / 2.0 + 1,
                        pen_width / 2.0 + 1,
                        radius,
                        radius,
                        self._start_angle,
                        -self._max_delta_angle)

        # draw foreground circle
        pen_foreground = QPen()
        pen_foreground.setWidth(pen_width)
        pen_foreground.setColor(self._color)
        pen_foreground.setCapStyle(Qt.RoundCap)
        painter.setPen(pen_foreground)
        painter.drawArc(pen_width / 2.0 + 1,
                        pen_width / 2.0 + 1,
                        radius,
                        radius,
                        self._start_angle,
                        -percent * 0.01 * self._max_delta_angle)
        painter.end()

    @classmethod
    def dashboard(cls, parent=None):
        """Create a dashboard style MCircle"""
        return MProgressCircle(dashboard=True, parent=parent)
Пример #4
0
class MDivider(QtWidgets.QWidget):
    """
    A divider line separates different content.

    Property:
        dayu_text: six.string_types
    """

    _alignment_map = {
        QtCore.Qt.AlignCenter: 50,
        QtCore.Qt.AlignLeft: 20,
        QtCore.Qt.AlignRight: 80,
    }

    def __init__(
        self,
        text="",
        orientation=QtCore.Qt.Horizontal,
        alignment=QtCore.Qt.AlignCenter,
        parent=None,
    ):
        super(MDivider, self).__init__(parent)
        self._orient = orientation
        self._text_label = MLabel().secondary()
        self._left_frame = QtWidgets.QFrame()
        self._right_frame = QtWidgets.QFrame()
        self._main_lay = QtWidgets.QHBoxLayout()
        self._main_lay.setContentsMargins(0, 0, 0, 0)
        self._main_lay.setSpacing(0)
        self._main_lay.addWidget(self._left_frame)
        self._main_lay.addWidget(self._text_label)
        self._main_lay.addWidget(self._right_frame)
        self.setLayout(self._main_lay)

        if orientation == QtCore.Qt.Horizontal:
            self._left_frame.setFrameShape(QtWidgets.QFrame.HLine)
            self._left_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
            self._right_frame.setFrameShape(QtWidgets.QFrame.HLine)
            self._right_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
        else:
            self._text_label.setVisible(False)
            self._right_frame.setVisible(False)
            self._left_frame.setFrameShape(QtWidgets.QFrame.VLine)
            self._left_frame.setFrameShadow(QtWidgets.QFrame.Plain)
            self.setFixedWidth(2)
        self._main_lay.setStretchFactor(self._left_frame,
                                        self._alignment_map.get(alignment, 50))
        self._main_lay.setStretchFactor(
            self._right_frame, 100 - self._alignment_map.get(alignment, 50))
        self._text = None
        self.set_dayu_text(text)

    def set_dayu_text(self, value):
        """
        Set the divider's text.
        When text is empty, hide the text_label and right_frame to ensure the divider not has a gap.

        :param value: six.string_types
        :return: None
        """
        self._text = value
        self._text_label.setText(value)
        if self._orient == QtCore.Qt.Horizontal:
            self._text_label.setVisible(bool(value))
            self._right_frame.setVisible(bool(value))

    def get_dayu_text(self):
        """
        Get current text
        :return: six.string_types
        """
        return self._text

    dayu_text = QtCore.Property(six.string_types[0], get_dayu_text,
                                set_dayu_text)

    @classmethod
    def left(cls, text=""):
        """Create a horizontal divider with text at left."""
        return cls(text, alignment=QtCore.Qt.AlignLeft)

    @classmethod
    def right(cls, text=""):
        """Create a horizontal divider with text at right."""
        return cls(text, alignment=QtCore.Qt.AlignRight)

    @classmethod
    def center(cls, text=""):
        """Create a horizontal divider with text at center."""
        return cls(text, alignment=QtCore.Qt.AlignCenter)

    @classmethod
    def vertical(cls):
        """Create a vertical divider"""
        return cls(orientation=QtCore.Qt.Vertical)