Exemple #1
0
class MNewTag(QWidget):
    sig_add_tag = Signal(str)

    def __init__(self, text='New Tag', parent=None):
        super(MNewTag, self).__init__(parent)
        self.setAttribute(Qt.WA_StyledBackground)
        self._add_button = MToolButton().tiny().svg(
            'add_line.svg').text_beside_icon()
        self._add_button.setText(text)
        self._add_button.clicked.connect(self._slot_show_edit)
        self._line_edit = MLineEdit().tiny()
        self._line_edit.returnPressed.connect(self._slot_return_pressed)
        self._line_edit.setVisible(False)

        self._main_lay = QGridLayout()
        self._main_lay.setContentsMargins(3, 3, 3, 3)
        self._main_lay.addWidget(self._add_button, 0, 0)
        self._main_lay.addWidget(self._line_edit, 0, 0)
        self.setLayout(self._main_lay)

    def set_completer(self, completer):
        self._line_edit.setCompleter(completer)

    def _slot_show_edit(self):
        self._line_edit.setVisible(True)
        self._add_button.setVisible(False)
        self._line_edit.setFocus(Qt.MouseFocusReason)

    def _slot_return_pressed(self):
        self._line_edit.setVisible(False)
        self._add_button.setVisible(True)
        if self._line_edit.text():
            self.sig_add_tag.emit(self._line_edit.text())
        self._line_edit.clear()

    def focusOutEvent(self, *args, **kwargs):
        self._line_edit.setVisible(False)
        self._add_button.setVisible(True)
        return super(MNewTag, self).focusOutEvent(*args, **kwargs)
Exemple #2
0
class SearchableMenuBase(ScrollableMenuBase):
    def __init__(self, *args, **kwargs):
        super(SearchableMenuBase, self).__init__(*args, **kwargs)
        self.search_popup = MPopup(self)
        self.search_popup.setVisible(False)
        self.search_bar = MLineEdit(self)
        self.search_label = QtWidgets.QLabel()

        self.search_bar.textChanged.connect(self.slot_search_change)
        self.search_bar.keyPressEvent = partial(
            self.search_key_event, self.search_bar.keyPressEvent
        )
        self.aboutToHide.connect(lambda: self.search_bar.setText(""))

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.search_label)
        layout.addWidget(self.search_bar)
        self.search_popup.setLayout(layout)

        self.setProperty("search_placeholder", self.tr("Search Action..."))
        self.setProperty("search_label", self.tr("Search Action..."))

        self.setProperty("searchable", True)
        self.setProperty("search_re", "I")

    def search_key_event(self, call, event):
        key = event.key()
        # NOTES: support menu original key event on search bar
        if key in (
            QtCore.Qt.Key_Up,
            QtCore.Qt.Key_Down,
            QtCore.Qt.Key_Return,
            QtCore.Qt.Key_Enter,
        ):
            super(SearchableMenuBase, self).keyPressEvent(event)
        elif key == QtCore.Qt.Key_Tab:
            self.search_bar.setFocus()
        return call(event)

    def _set_search_label(self, value):
        self.search_label.setText(value)

    def _set_search_placeholder(self, value):
        self.search_bar.setPlaceholderText(value)

    def _set_search_re(self, value):
        if not isinstance(value, six.text_type):
            raise TypeError("`search_re` property should be a string type")

    def slot_search_change(self, text):
        flags = 0
        for m in self.property("search_re") or "":
            flags |= getattr(re, m.upper(), 0)
        search_reg = re.compile(r".*%s.*" % text, flags)
        self._update_search(search_reg)

    def _update_search(self, search_reg, parent_menu=None):
        actions = parent_menu.actions() if parent_menu else self.actions()
        vis_list = []
        for action in actions:
            menu = action.menu()
            if not menu:
                is_match = bool(re.match(search_reg, action.text()))
                action.setVisible(is_match)
                is_match and vis_list.append(action)
            else:
                is_match = bool(re.match(search_reg, menu.title()))
                self._update_search("" if is_match else search_reg, menu)

        if parent_menu:
            parent_menu.menuAction().setVisible(bool(vis_list) or not search_reg)

    def keyPressEvent(self, event):
        key = event.key()
        if self.property("searchable"):
            # NOTES(timmyliang): 26 character trigger search bar
            if 65 <= key <= 90:
                char = chr(key)
                self.search_bar.setText(char)
                self.search_bar.setFocus()
                self.search_bar.selectAll()
                width = self.sizeHint().width()
                width = width if width >= 50 else 50
                offset = QtCore.QPoint(width, 0)
                self.search_popup.move(self.pos() + offset)
                self.search_popup.show()
            elif key == QtCore.Qt.Key_Escape:
                self.search_bar.setText("")
                self.search_popup.hide()
        return super(SearchableMenuBase, self).keyPressEvent(event)
Exemple #3
0
class MNewTag(QWidget):
    """New Tag input component."""

    sig_add_tag = Signal(str)

    def __init__(self, text="New Tag", parent=None):
        super(MNewTag, self).__init__(parent)
        self.setAttribute(Qt.WA_StyledBackground)
        self._add_button = MToolButton().text_beside_icon().small().svg(
            "add_line.svg")
        self._add_button.setText(text)
        self._add_button.clicked.connect(self._slot_show_edit)
        self._line_edit = MLineEdit().small()
        self._line_edit.returnPressed.connect(self._slot_return_pressed)
        self._line_edit.setVisible(False)
        self._line_edit.installEventFilter(self)

        self._main_lay = QGridLayout()
        self._main_lay.setContentsMargins(3, 3, 3, 3)
        self._main_lay.addWidget(self._add_button, 0, 0)
        self._main_lay.addWidget(self._line_edit, 0, 0)
        self.setLayout(self._main_lay)
        scale_x, _ = get_scale_factor()
        style = QssTemplate("""
            MNewTag{
                border: @border@unit dashed @border_color;
            }
            MNewTag MToolButton:hover{
                border:none;
            }
            """)
        self.setStyleSheet(
            style.substitute(
                border_color=utils.fade_color(dayu_theme.secondary_text_color,
                                              "35%"),
                unit=dayu_theme.unit,
                border=1 * scale_x,
            ))

    def set_completer(self, completer):
        """Set the input completer"""
        self._line_edit.setCompleter(completer)

    def _slot_show_edit(self):
        self._line_edit.setVisible(True)
        self._add_button.setVisible(False)
        self._line_edit.setFocus(Qt.MouseFocusReason)

    def _slot_return_pressed(self):
        self._line_edit.setVisible(False)
        self._add_button.setVisible(True)
        if self._line_edit.text():
            self.sig_add_tag.emit(self._line_edit.text())
        self._line_edit.clear()
        self.update()

    def focusOutEvent(self, *args, **kwargs):
        """Override focusOutEvent to change the edit mode to button mode."""
        self._line_edit.setVisible(False)
        self._add_button.setVisible(True)
        return super(MNewTag, self).focusOutEvent(*args, **kwargs)

    def eventFilter(self, widget, event):
        if widget is self._line_edit:
            if event.type() == QEvent.Type.KeyPress and event.key(
            ) == Qt.Key_Escape:
                self._line_edit.setVisible(False)
                self._add_button.setVisible(True)

        return super(MNewTag, self).eventFilter(widget, event)