예제 #1
0
class MPushButtonGroup(MButtonGroupBase):
    def __init__(self, orientation=QtCore.Qt.Horizontal, parent=None):
        super(MPushButtonGroup, self).__init__(orientation=orientation,
                                               parent=parent)
        self.set_spacing(1)
        self._dayu_type = MPushButton.PrimaryType
        self._dayu_size = dayu_theme.default_size
        self._button_group.setExclusive(False)

    def create_button(self, data_dict):
        button = MPushButton()
        button.set_dayu_size(data_dict.get("dayu_size", self._dayu_size))
        button.set_dayu_type(data_dict.get("dayu_type", self._dayu_type))
        return button

    def get_dayu_size(self):
        return self._dayu_size

    def get_dayu_type(self):
        return self._dayu_type

    def set_dayu_size(self, value):
        self._dayu_size = value

    def set_dayu_type(self, value):
        self._dayu_type = value

    dayu_size = QtCore.Property(int, get_dayu_size, set_dayu_size)
    dayu_type = QtCore.Property(str, get_dayu_type, set_dayu_type)
예제 #2
0
class MClickBrowserFolderToolButton(MToolButton):
    """A Clickable tool button to browser folders"""

    sig_folder_changed = QtCore.Signal(str)
    sig_folders_changed = QtCore.Signal(list)
    slot_browser_folder = _slot_browser_folder

    def __init__(self, multiple=False, parent=None):
        super(MClickBrowserFolderToolButton, self).__init__(parent=parent)

        self.set_dayu_svg("folder_line.svg")
        self.icon_only()
        self.clicked.connect(self.slot_browser_folder)
        self.setToolTip(self.tr("Click to browser folder"))

        self._path = None
        self._multiple = multiple

    def get_dayu_path(self):
        """
        Get last browser file path
        :return: str
        """
        return self._path

    def set_dayu_path(self, value):
        """
        Set browser file start path
        :param value: str
        :return: None
        """
        self._path = value

    def get_dayu_multiple(self):
        """
        Get browser can select multiple file or not
        :return: bool
        """
        return self._multiple

    def set_dayu_multiple(self, value):
        """
        Set browser can select multiple file or not
        :param value: bool
        :return: None
        """
        self._multiple = value

    dayu_multiple = QtCore.Property(bool, get_dayu_multiple, set_dayu_multiple)
    dayu_path = QtCore.Property(six.string_types[0], get_dayu_path,
                                set_dayu_path)
예제 #3
0
class MClickSaveFileToolButton(MToolButton):
    """A Clickable tool button to browser files"""

    sig_file_changed = QtCore.Signal(str)
    slot_browser_file = _slot_save_file

    def __init__(self, multiple=False, parent=None):
        super(MClickSaveFileToolButton, self).__init__(parent=parent)
        self.set_dayu_svg("save_line.svg")
        self.icon_only()
        self.clicked.connect(self.slot_browser_file)
        self.setToolTip(self.tr("Click to save file"))

        self._path = None
        self._multiple = multiple
        self._filters = []

    def get_dayu_filters(self):
        """
        Get browser's format filters
        :return: list
        """
        return self._filters

    def set_dayu_filters(self, value):
        """
        Set browser file format filters
        :param value:
        :return: None
        """
        self._filters = value

    def get_dayu_path(self):
        """
        Get last browser file path
        :return: str
        """
        return self._path

    def set_dayu_path(self, value):
        """
        Set browser file start path
        :param value: str
        :return: None
        """
        self._path = value

    dayu_path = QtCore.Property(six.string_types[0], get_dayu_path,
                                set_dayu_path)
    dayu_filters = QtCore.Property(list, get_dayu_filters, set_dayu_filters)
예제 #4
0
class MTimeEdit(QtWidgets.QTimeEdit):
    """
    MTimeEdit just use stylesheet and add dayu_size. No more extend.
    Property:
        dayu_size: The height of MTimeEdit
    """

    def __init__(self, time=None, parent=None):
        if time is None:
            super(MTimeEdit, self).__init__(parent=parent)
        else:
            super(MTimeEdit, self).__init__(time, parent=parent)
        self._dayu_size = dayu_theme.default_size

    def get_dayu_size(self):
        """
        Get the MTimeEdit height
        :return: integer
        """
        return self._dayu_size

    def set_dayu_size(self, value):
        """
        Set the MTimeEdit size.
        :param value: integer
        :return: None
        """
        self._dayu_size = value
        self.style().polish(self)

    dayu_size = QtCore.Property(int, get_dayu_size, set_dayu_size)

    def huge(self):
        """Set MTimeEdit to huge size"""
        self.set_dayu_size(dayu_theme.huge)
        return self

    def large(self):
        """Set MTimeEdit to large size"""
        self.set_dayu_size(dayu_theme.large)
        return self

    def medium(self):
        """Set MTimeEdit to  medium"""
        self.set_dayu_size(dayu_theme.medium)
        return self

    def small(self):
        """Set MTimeEdit to small size"""
        self.set_dayu_size(dayu_theme.small)
        return self

    def tiny(self):
        """Set MTimeEdit to tiny size"""
        self.set_dayu_size(dayu_theme.tiny)
        return self
예제 #5
0
파일: bind2.py 프로젝트: z199416/MayaScript
def bind(typ,objectName, propertyName ,getter = None ,setter = None):

    def _getter(self):
        print ("getter objectName ",objectName)
        return self.findChild(QtCore.QObject, objectName).property(propertyName)
    
    def _setter(self, value):
        print ("setter objectName ",objectName,value)
        self.findChild(QtCore.QObject, objectName).setProperty(propertyName, value)
    
    return QtCore.Property(typ,_getter,_setter)
예제 #6
0
class MDoubleSpinBox(QtWidgets.QDoubleSpinBox):
    """
    MDoubleSpinBox just use stylesheet and add dayu_size. No more extend.
    Property:
        dayu_size: The height of MDoubleSpinBox
    """

    def __init__(self, parent=None):
        super(MDoubleSpinBox, self).__init__(parent=parent)
        self._dayu_size = dayu_theme.default_size

    def get_dayu_size(self):
        """
        Get the MDoubleSpinBox height
        :return: integer
        """
        return self._dayu_size

    def set_dayu_size(self, value):
        """
        Set the MDoubleSpinBox size.
        :param value: integer
        :return: None
        """
        self._dayu_size = value
        self.style().polish(self)

    dayu_size = QtCore.Property(int, get_dayu_size, set_dayu_size)

    def huge(self):
        """Set MDoubleSpinBox to huge size"""
        self.set_dayu_size(dayu_theme.huge)
        return self

    def large(self):
        """Set MDoubleSpinBox to large size"""
        self.set_dayu_size(dayu_theme.large)
        return self

    def medium(self):
        """Set MDoubleSpinBox to  medium"""
        self.set_dayu_size(dayu_theme.medium)
        return self

    def small(self):
        """Set MDoubleSpinBox to small size"""
        self.set_dayu_size(dayu_theme.small)
        return self

    def tiny(self):
        """Set MDoubleSpinBox to tiny size"""
        self.set_dayu_size(dayu_theme.tiny)
        return self
예제 #7
0
class MToolButtonGroup(MButtonGroupBase):
    sig_checked_changed = QtCore.Signal(int)

    def __init__(
        self,
        size=None,
        type=None,
        exclusive=False,
        orientation=QtCore.Qt.Horizontal,
        parent=None,
    ):
        super(MToolButtonGroup, self).__init__(orientation=orientation,
                                               parent=parent)
        self.set_spacing(1)
        self._button_group.setExclusive(exclusive)
        self._size = size
        self._type = type
        self._button_group.buttonClicked[int].connect(self.sig_checked_changed)

    def create_button(self, data_dict):
        button = MToolButton()
        if data_dict.get("svg"):
            button.svg(data_dict.get("svg"))
        if data_dict.get("text"):
            if data_dict.get("svg") or data_dict.get("icon"):
                button.text_beside_icon()
            else:
                button.text_only()
        else:
            button.icon_only()
        return button

    def set_dayu_checked(self, value):
        if value == self.get_dayu_checked():
            return
        button = self._button_group.button(value)
        if button:
            button.setChecked(True)
            self.sig_checked_changed.emit(value)
        else:
            print("error")

    def get_dayu_checked(self):
        return self._button_group.checkedId()

    dayu_checked = QtCore.Property(int,
                                   get_dayu_checked,
                                   set_dayu_checked,
                                   notify=sig_checked_changed)
예제 #8
0
class MProgressBar(QtWidgets.QProgressBar):
    """
    props:
        status: str

    """

    ErrorStatus = "error"
    NormalStatus = "primary"
    SuccessStatus = "success"

    def __init__(self, parent=None):
        super(MProgressBar, self).__init__(parent=parent)
        self.setAlignment(QtCore.Qt.AlignCenter)
        self._status = MProgressBar.NormalStatus

    def auto_color(self):
        self.valueChanged.connect(self._update_color)
        return self

    @QtCore.Slot(int)
    def _update_color(self, value):
        if value >= self.maximum():
            self.set_dayu_status(MProgressBar.SuccessStatus)
        else:
            self.set_dayu_status(MProgressBar.NormalStatus)

    def get_dayu_status(self):
        return self._status

    def set_dayu_status(self, value):
        self._status = value
        self.style().polish(self)

    dayu_status = QtCore.Property(str, get_dayu_status, set_dayu_status)

    def normal(self):
        self.set_dayu_status(MProgressBar.NormalStatus)
        return self

    def error(self):
        self.set_dayu_status(MProgressBar.ErrorStatus)
        return self

    def success(self):
        self.set_dayu_status(MProgressBar.SuccessStatus)
        return self
예제 #9
0
class TestLabel(QtWidgets.QLabel):
    def __init__(self, parent=None):
        super(TestLabel, self).__init__(parent)
        self.text3 = "123"

    def getString(self):
        print("getString call")
        return self.text()

    def setString(self, text):
        self.setText("text2: %s" % text)

    text2 = QtCore.Property(str, getString, setString)

    @property
    def text3(self):
        return self.text()

    @text3.setter
    def text3(self, text):
        self.setText("text3: %s" % text)
예제 #10
0
class MRadioButtonGroup(MButtonGroupBase):
    """
    Property:
        dayu_checked
    """

    sig_checked_changed = QtCore.Signal(int)

    def __init__(self, orientation=QtCore.Qt.Horizontal, parent=None):
        super(MRadioButtonGroup, self).__init__(orientation=orientation,
                                                parent=parent)
        scale_x, _ = get_scale_factor()
        self.set_spacing(15 * scale_x)
        self._button_group.setExclusive(True)
        self._button_group.buttonClicked[int].connect(self.sig_checked_changed)

    def create_button(self, data_dict):
        return MRadioButton()

    def set_dayu_checked(self, value):
        if value == self.get_dayu_checked():
            return
        button = self._button_group.button(value)
        if button:
            button.setChecked(True)
            self.sig_checked_changed.emit(value)
        else:
            print("error")

    def get_dayu_checked(self):
        return self._button_group.checkedId()

    dayu_checked = QtCore.Property(int,
                                   get_dayu_checked,
                                   set_dayu_checked,
                                   notify=sig_checked_changed)
예제 #11
0
class ScreenMarquee(QtWidgets.QDialog):
    """Dialog to interactively define screen area.

    This allows to select a screen area through a marquee selection.
    """
    def __init__(self, parent=None):
        """Constructor"""
        super(ScreenMarquee, self).__init__(parent=parent)

        self._opacity = 1
        self._click_pos = None
        self._capture_rect = QtCore.QRect()

        self.setWindowFlags(QtCore.Qt.FramelessWindowHint
                            | QtCore.Qt.WindowStaysOnTopHint
                            | QtCore.Qt.CustomizeWindowHint | QtCore.Qt.Tool)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.setCursor(QtCore.Qt.CrossCursor)
        self.setMouseTracking(True)

        desktop = QtWidgets.QApplication.desktop()
        desktop.resized.connect(self._fit_screen_geometry)
        desktop.screenCountChanged.connect(self._fit_screen_geometry)

    @property
    def capture_rect(self):
        """The resulting QRect from a previous capture operation."""
        return self._capture_rect

    def paintEvent(self, event):
        """Paint event"""

        # Convert click and current mouse positions to local space.
        mouse_pos = self.mapFromGlobal(QtGui.QCursor.pos())
        click_pos = None
        if self._click_pos is not None:
            click_pos = self.mapFromGlobal(self._click_pos)

        painter = QtGui.QPainter(self)

        # Draw background. Aside from aesthetics, this makes the full
        # tool region accept mouse events.
        painter.setBrush(QtGui.QColor(0, 0, 0, self._opacity))
        painter.setPen(QtCore.Qt.NoPen)
        painter.drawRect(event.rect())

        # Clear the capture area
        if click_pos is not None:
            capture_rect = QtCore.QRect(click_pos, mouse_pos)
            painter.setCompositionMode(painter.CompositionMode_Clear)
            painter.drawRect(capture_rect)
            painter.setCompositionMode(painter.CompositionMode_SourceOver)

        pen_color = QtGui.QColor(255, 255, 255, 64)
        pen = QtGui.QPen(pen_color, 1, QtCore.Qt.DotLine)
        painter.setPen(pen)

        # Draw cropping markers at click position
        rect = event.rect()
        if click_pos is not None:
            painter.drawLine(rect.left(), click_pos.y(), rect.right(),
                             click_pos.y())
            painter.drawLine(click_pos.x(), rect.top(), click_pos.x(),
                             rect.bottom())

        # Draw cropping markers at current mouse position
        painter.drawLine(rect.left(), mouse_pos.y(), rect.right(),
                         mouse_pos.y())
        painter.drawLine(mouse_pos.x(), rect.top(), mouse_pos.x(),
                         rect.bottom())

    def mousePressEvent(self, event):
        """Mouse click event"""

        if event.button() == QtCore.Qt.LeftButton:
            # Begin click drag operation
            self._click_pos = event.globalPos()

    def mouseReleaseEvent(self, event):
        """Mouse release event"""
        if event.button(
        ) == QtCore.Qt.LeftButton and self._click_pos is not None:
            # End click drag operation and commit the current capture rect
            self._capture_rect = QtCore.QRect(self._click_pos,
                                              event.globalPos()).normalized()
            self._click_pos = None
        self.close()

    def mouseMoveEvent(self, event):
        """Mouse move event"""
        self.repaint()

    @classmethod
    def capture_pixmap(cls):
        """Modally capture screen with marquee into pixmap.

        Returns:
            QtGui.QPixmap: Captured pixmap image
        """

        tool = cls()
        tool.exec_()
        return get_desktop_pixmap(tool.capture_rect)

    @classmethod
    def capture_file(cls, filepath=None):

        if filepath is None:
            filepath = tempfile.NamedTemporaryFile(prefix="screenshot_",
                                                   suffix=".png",
                                                   delete=False).name
        pixmap = cls.capture_pixmap()
        pixmap.save(filepath)
        return filepath

    def showEvent(self, event):
        """
        Show event
        """
        self._fit_screen_geometry()

        # Start fade in animation
        fade_anim = QtCore.QPropertyAnimation(self, "_opacity_anim_prop", self)
        fade_anim.setStartValue(self._opacity)
        fade_anim.setEndValue(50)
        fade_anim.setDuration(200)
        fade_anim.setEasingCurve(QtCore.QEasingCurve.OutCubic)
        fade_anim.start(QtCore.QAbstractAnimation.DeleteWhenStopped)

    def _set_opacity(self, value):
        """
        Animation callback for opacity
        """
        self._opacity = value
        self.repaint()

    def _get_opacity(self):
        """
        Animation callback for opacity
        """
        return self._opacity

    _opacity_anim_prop = QtCore.Property(int, _get_opacity, _set_opacity)

    def _fit_screen_geometry(self):
        # Compute the union of all screen geometries, and resize to fit.
        desktop = QtWidgets.QApplication.desktop()
        workspace_rect = QtCore.QRect()
        for i in range(desktop.screenCount()):
            workspace_rect = workspace_rect.united(desktop.screenGeometry(i))
        self.setGeometry(workspace_rect)
예제 #12
0
        class TestContainer(QtWidgets.QWidget):

            msg = QtCore.Property(
                str, self.label.text,
                lambda instance, val: self.label.setText("test : %s" % val))
예제 #13
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)
예제 #14
0
class MAvatar(QtWidgets.QLabel):
    """
    Avatar component. It can be used to represent people or object.

    Property:
        image: avatar image, should be QPixmap.
        dayu_size: the size of image.
    """

    def __init__(self, parent=None, flags=QtCore.Qt.Widget):
        super(MAvatar, self).__init__(parent, flags)
        self._default_pix = MPixmap("user_fill.svg")
        self._pixmap = self._default_pix
        self._dayu_size = 0
        self.set_dayu_size(dayu_theme.default_size)

    def set_dayu_size(self, value):
        """
        Set the avatar size.
        :param value: integer
        :return: None
        """
        self._dayu_size = value
        self._set_dayu_size()

    def _set_dayu_size(self):
        self.setFixedSize(QtCore.QSize(self._dayu_size, self._dayu_size))
        self._set_dayu_image()

    def _set_dayu_image(self):
        self.setPixmap(
            self._pixmap.scaledToWidth(self.height(), QtCore.Qt.SmoothTransformation)
        )

    def set_dayu_image(self, value):
        """
        Set avatar image.
        :param value: QPixmap or None.
        :return: None
        """
        if value is None:
            self._pixmap = self._default_pix
        elif isinstance(value, QtGui.QPixmap):
            self._pixmap = self._default_pix if value.isNull() else value
        else:
            raise TypeError(
                "Input argument 'value' should be QPixmap or None, "
                "but get {}".format(type(value))
            )
        self._set_dayu_image()

    def get_dayu_image(self):
        """
        Get the avatar image.
        :return: QPixmap
        """
        return self._pixmap

    def get_dayu_size(self):
        """
        Get the avatar size
        :return: integer
        """
        return self._dayu_size

    dayu_image = QtCore.Property(QtGui.QPixmap, get_dayu_image, set_dayu_image)
    dayu_size = QtCore.Property(int, get_dayu_size, set_dayu_size)

    @classmethod
    def huge(cls, image=None):
        """Create a MAvatar with huge size"""
        inst = cls()
        inst.set_dayu_size(dayu_theme.huge)
        inst.set_dayu_image(image)
        return inst

    @classmethod
    def large(cls, image=None):
        """Create a MAvatar with large size"""
        inst = cls()
        inst.set_dayu_size(dayu_theme.large)
        inst.set_dayu_image(image)
        return inst

    @classmethod
    def medium(cls, image=None):
        """Create a MAvatar with medium size"""
        inst = cls()
        inst.set_dayu_size(dayu_theme.medium)
        inst.set_dayu_image(image)
        return inst

    @classmethod
    def small(cls, image=None):
        """Create a MAvatar with small size"""
        inst = cls()
        inst.set_dayu_size(dayu_theme.small)
        inst.set_dayu_image(image)
        return inst

    @classmethod
    def tiny(cls, image=None):
        """Create a MAvatar with tiny size"""
        inst = cls()
        inst.set_dayu_size(dayu_theme.tiny)
        inst.set_dayu_image(image)
        return inst
예제 #15
0
class MClickBrowserFilePushButton(MPushButton):
    """A Clickable push button to browser files"""

    sig_file_changed = QtCore.Signal(str)
    sig_files_changed = QtCore.Signal(list)
    slot_browser_file = _slot_browser_file

    def __init__(self, text="Browser", multiple=False, parent=None):
        super(MClickBrowserFilePushButton, self).__init__(text=text,
                                                          parent=parent)
        self.setProperty("multiple", multiple)
        self.clicked.connect(self.slot_browser_file)
        self.setToolTip(self.tr("Click to browser file"))

        self._path = None
        self._multiple = multiple
        self._filters = []

    def get_dayu_filters(self):
        """
        Get browser's format filters
        :return: list
        """
        return self._filters

    def set_dayu_filters(self, value):
        """
        Set browser file format filters
        :param value:
        :return: None
        """
        self._filters = value

    def get_dayu_path(self):
        """
        Get last browser file path
        :return: str
        """
        return self._path

    def set_dayu_path(self, value):
        """
        Set browser file start path
        :param value: str
        :return: None
        """
        self._path = value

    def get_dayu_multiple(self):
        """
        Get browser can select multiple file or not
        :return: bool
        """
        return self._multiple

    def set_dayu_multiple(self, value):
        """
        Set browser can select multiple file or not
        :param value: bool
        :return: None
        """
        self._multiple = value

    dayu_multiple = QtCore.Property(bool, get_dayu_multiple, set_dayu_multiple)
    dayu_path = QtCore.Property(six.string_types[0], get_dayu_path,
                                set_dayu_path)
    dayu_filters = QtCore.Property(list, get_dayu_filters, set_dayu_filters)
예제 #16
0
class MDragFolderButton(MToolButton):
    """A Clickable and draggable tool button to browser folders"""

    sig_folder_changed = QtCore.Signal(str)
    sig_folders_changed = QtCore.Signal(list)
    slot_browser_folder = _slot_browser_folder

    def __init__(self, multiple=False, parent=None):
        super(MDragFolderButton, self).__init__(parent=parent)
        self.setAcceptDrops(True)
        self.setMouseTracking(True)
        self.text_under_icon()
        self.set_dayu_svg("folder_line.svg")
        size = dayu_theme.drag_size
        self.set_dayu_size(size)
        self.setIconSize(QtCore.QSize(size, size))
        self.setText(self.tr("Click or drag folder here"))
        self.clicked.connect(self.slot_browser_folder)
        self.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                           QtWidgets.QSizePolicy.Expanding)
        self.setToolTip(self.tr("Click to browser folder or drag folder here"))

        self._path = None
        self._multiple = multiple

    def get_dayu_path(self):
        """
        Get last browser file path
        :return: str
        """
        return self._path

    def set_dayu_path(self, value):
        """
        Set browser file start path
        :param value: str
        :return: None
        """
        self._path = value

    def get_dayu_multiple(self):
        """
        Get browser can select multiple file or not
        :return: bool
        """
        return self._multiple

    def set_dayu_multiple(self, value):
        """
        Set browser can select multiple file or not
        :param value: bool
        :return: None
        """
        self._multiple = value

    dayu_multiple = QtCore.Property(bool, get_dayu_multiple, set_dayu_multiple)
    dayu_path = QtCore.Property(bool, get_dayu_path, set_dayu_path)

    def dragEnterEvent(self, event):
        """Override dragEnterEvent. Validate dragged folders"""
        if event.mimeData().hasFormat("text/uri-list"):
            folder_list = [
                url.toLocalFile() for url in event.mimeData().urls()
                if os.path.isdir(url.toLocalFile())
            ]
            count = len(folder_list)
            if count == 1 or (count > 1 and self.get_dayu_multiple()):
                event.acceptProposedAction()
                return

    def dropEvent(self, event):
        """Override dropEvent to accept the dropped folders"""
        folder_list = [
            url.toLocalFile() for url in event.mimeData().urls()
            if os.path.isdir(url.toLocalFile())
        ]
        if self.get_dayu_multiple():
            self.sig_folders_changed.emit(folder_list)
        else:
            self.sig_folder_changed.emit(folder_list[0])
        self.set_dayu_path(folder_list[0])