# coding: utf-8 from typing import Union from PySide6.QtCore import QSize, Qt, QRectF, Signal from PySide6.QtGui import QPainter, QPainterPath, QIcon from PySide6.QtWidgets import QHBoxLayout, QLineEdit, QToolButton, QTextEdit, QPlainTextEdit from ...common.style_sheet import FluentStyleSheet, themeColor from ...common.icon import isDarkTheme, FluentIconBase, drawIcon from ...common.icon import FluentIcon as FIF from ...common.font import setFont from .menu import LineEditMenu, TextEditMenu from .scroll_bar import SmoothScrollDelegate class LineEditButton(QToolButton): """ Line edit button """ def __init__(self, icon: Union[str, QIcon, FluentIconBase], parent=None): super().__init__(parent=parent) self._icon = icon self.isPressed = False self.setFixedSize(31, 23) self.setIconSize(QSize(10, 10)) self.setCursor(Qt.CursorShape.PointingHandCursor) self.setObjectName('lineEditButton') FluentStyleSheet.LINE_EDIT.apply(self) def mousePressEvent(self, e): self.isPressed = True super().mousePressEvent(e) def mouseReleaseEvent(self, e): self.isPressed = False super().mouseReleaseEvent(e) def paintEvent(self, e): super().paintEvent(e) painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) iw, ih = self.iconSize().width(), self.iconSize().height() w, h = self.width(), self.height() rect = QRectF((w - iw)/2, (h - ih)/2, iw, ih) if self.isPressed: painter.setOpacity(0.7) if isDarkTheme(): drawIcon(self._icon, painter, rect) else: drawIcon(self._icon, painter, rect, fill='#656565') class LineEdit(QLineEdit): """ Line edit """ def __init__(self, parent=None): super().__init__(parent=parent) self._isClearButtonEnabled = False self.setProperty("transparent", True) FluentStyleSheet.LINE_EDIT.apply(self) self.setFixedHeight(33) self.setAttribute(Qt.WA_MacShowFocusRect, False) setFont(self) self.hBoxLayout = QHBoxLayout(self) self.clearButton = LineEditButton(FIF.CLOSE, self) self.clearButton.setFixedSize(29, 25) self.clearButton.hide() self.hBoxLayout.setSpacing(3) self.hBoxLayout.setContentsMargins(4, 4, 4, 4) self.hBoxLayout.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.hBoxLayout.addWidget(self.clearButton, 0, Qt.AlignRight) self.clearButton.clicked.connect(self.clear) self.textChanged.connect(self.__onTextChanged) def setClearButtonEnabled(self, enable: bool): self._isClearButtonEnabled = enable self.setTextMargins(0, 0, 28*enable, 0) def isClearButtonEnabled(self) -> bool: return self._isClearButtonEnabled def focusOutEvent(self, e): super().focusOutEvent(e) self.clearButton.hide() def focusInEvent(self, e): super().focusInEvent(e) if self.isClearButtonEnabled(): self.clearButton.setVisible(bool(self.text())) def __onTextChanged(self, text): """ text changed slot """ if self.isClearButtonEnabled(): self.clearButton.setVisible(bool(text) and self.hasFocus()) def contextMenuEvent(self, e): menu = LineEditMenu(self) menu.exec_(e.globalPos()) def paintEvent(self, e): super().paintEvent(e) if not self.hasFocus(): return painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) painter.setPen(Qt.NoPen) m = self.contentsMargins() path = QPainterPath() w, h = self.width()-m.left()-m.right(), self.height() path.addRoundedRect(QRectF(m.left(), h-10, w, 10), 5, 5) rectPath = QPainterPath() rectPath.addRect(m.left(), h-10, w, 8) path = path.subtracted(rectPath) painter.fillPath(path, themeColor()) class SearchLineEdit(LineEdit): """ Search line edit """ searchSignal = Signal(str) clearSignal = Signal() def __init__(self, parent=None): super().__init__(parent) self.searchButton = LineEditButton(FIF.SEARCH, self) self.hBoxLayout.addWidget(self.searchButton, 0, Qt.AlignRight) self.setClearButtonEnabled(True) self.setTextMargins(0, 0, 59, 0) self.searchButton.clicked.connect(self.search) self.clearButton.clicked.connect(self.clearSignal) def search(self): """ emit search signal """ text = self.text().strip() if text: self.searchSignal.emit(text) else: self.clearSignal.emit() class TextEdit(QTextEdit): """ Text edit """ def __init__(self, parent=None): super().__init__(parent=parent) self.scrollDelegate = SmoothScrollDelegate(self) FluentStyleSheet.LINE_EDIT.apply(self) setFont(self) def contextMenuEvent(self, e): menu = TextEditMenu(self) menu.exec_(e.globalPos()) class PlainTextEdit(QPlainTextEdit): """ Plain text edit """ def __init__(self, parent=None): super().__init__(parent=parent) self.scrollDelegate = SmoothScrollDelegate(self) FluentStyleSheet.LINE_EDIT.apply(self) setFont(self) def contextMenuEvent(self, e): menu = TextEditMenu(self) menu.exec_(e.globalPos())