class BaseAnimObject(object): _glow_pens = {} for index in range(1, 11): _glow_pens[index] = [QPen(QColor(0, 255, 0, 12 * index), 1, Qt.SolidLine), QPen(QColor(0, 255, 0, 5 * index), 3, Qt.SolidLine), QPen(QColor(0, 255, 0, 2 * index), 5, Qt.SolidLine), QPen(QColor(0, 255, 0, 25.5 * index), 1, Qt.SolidLine)] _pens_text = QPen(QColor(202, 207, 210), 1, Qt.SolidLine) _pens_shadow = QPen(QColor(9, 10, 12), 1, Qt.SolidLine) _pens_border = QPen(QColor(9, 10, 12), 2, Qt.SolidLine) _pens_clear = QPen(QColor(0, 0, 0, 0), 1, Qt.SolidLine) _pens_text_disabled = QPen(QColor(102, 107, 110), 1, Qt.SolidLine) _pens_shadow_disabled = QPen(QColor(0, 0, 0), 1, Qt.SolidLine) _brush_clear = QBrush(QColor(0, 0, 0, 0)) _brush_border = QBrush(QColor(9, 10, 12)) def __init__(self): font = QFont() font.setPointSize(8) font.setFamily("Calibri") self.setFont(font) self._hover = False self._glow_index = 0 self._anim_timer = QTimer() self._anim_timer.timeout.connect(self._animate_glow) def enterEvent(self, event): super(self.__class__, self).enterEvent(event) if not self.isEnabled(): return self._hover = True self._start_anim() def leaveEvent(self, event): super(self.__class__, self).leaveEvent(event) if not self.isEnabled(): return self._hover = False self._start_anim() def _animate_glow(self): if self._hover: if self._glow_index >= 10: self._glow_index = 10 self._anim_timer.stop() else: self._glow_index += 1 else: if self._glow_index <= 0: self._glow_index = 0 self._anim_timer.stop() else: self._glow_index -= 1 dcc.execute_deferred(self.update) def _start_anim(self): if self._anim_timer.isActive(): return self._anim_timer.start(20)
class BaseLineEdit(QLineEdit, object): """ Basic line edit """ delayTextChanged = Signal(str) def __init__(self, text='', input_mode=None, parent=None): super(BaseLineEdit, self).__init__(text, parent) self._prefix_widget = None self._suffix_widget = None self._size = self.theme_default_size() self._main_layout = layouts.HorizontalLayout() self._main_layout.setContentsMargins(0, 0, 0, 0) self._main_layout.addStretch() self.setLayout(self._main_layout) self.setProperty('history', self.property('text')) self.setTextMargins(2, 0, 2, 0) if input_mode == 'float': self.setValidator(QDoubleValidator()) elif input_mode == 'int': self.setValidator(QIntValidator()) self._delay_timer = QTimer() self._delay_timer.setInterval(500) self._delay_timer.setSingleShot(True) self._delay_timer.timeout.connect(self._on_delay_text_changed) # ================================================================================================================= # PROPERTIES # ================================================================================================================= def _get_text(self): return self.text() def _set_text(self, value): with qt_contexts.block_signals(self): self.setText(value) def _get_size(self): """ Returns the spin box height size :return: float """ return self._size def _set_size(self, value): """ Sets spin box height size :param value: float """ self._size = value if hasattr(self._prefix_widget, 'theme_size'): self._prefix_widget.theme_size = self._size if hasattr(self._suffix_widget, 'theme_size'): self._suffix_widget.theme_size = self._size self.style().polish(self) theme_size = Property(int, _get_size, _set_size) line_text = Property(str, _get_text, _set_text) # ================================================================================================================= # OVERRIDES # ================================================================================================================= def setText(self, text): """ Overrides base QLineEdit setText base function. Save history :param text: str """ self.setProperty('history', '{}\n{}'.format(self.property('history'), text)) return super(BaseLineEdit, self).setText(text) def clear(self): """ Overrides base QLineEdit clear function :return: """ self.setProperty('history', '') return super(BaseLineEdit, self).clear() def keyPressEvent(self, event): """ Overrides base QLineEdit keyPressEvent function :param event: QKeyEvent """ if event.key() not in [Qt.Key_Enter, Qt.Key_Tab]: if self._delay_timer.isActive(): self._delay_timer.stop() self._delay_timer.start() super(BaseLineEdit, self).keyPressEvent(event) # ================================================================================================================= # BASE # ================================================================================================================= def set_delay_duration(self, ms): """ Sets the delay timer duration :param ms: float """ self._delay_timer.setInterval(ms) def get_prefix_widget(self): """ Returns prefix widget for user to edit :return: QWidget """ return self._prefix_widget def set_prefix_widget(self, widget): """ Sets the edit line left start widget :param widget: QWidget :return: QWidget """ if self._prefix_widget: index = self._main_layout.indexOf(self._prefix_widget) self._main_layout.takeAt(index) self._prefix_widget.setVisible(False) self._prefix_widget.deleteLater() widget.setProperty('combine', 'horizontal') widget.setProperty('position', 'left') if hasattr(widget, 'theme_size'): widget.them_size = self.theme_size margin = self.textMargins() margin.setLeft(margin.left() + widget.width()) self.setTextMargins(margin) self._main_layout.insertWidget(0, widget) self._prefix_widget = widget return widget def get_suffix_widget(self): """ Returns suffix widget for user to edit :return: QWidget """ return self._suffix_widget def set_suffix_widget(self, widget): """ Sets the edit line right start widget :param widget: QWidget :return: QWidget """ if self._suffix_widget: index = self._main_layout.indexOf(self._suffix_widget) self._main_layout.takeAt(index) self._suffix_widget.setVisible(False) self._suffix_widget.deleteLater() widget.setProperty('combine', 'horizontal') widget.setProperty('position', 'right') if hasattr(widget, 'theme_size'): widget.them_size = self.theme_size margin = self.textMargins() margin.setRight(margin.right() + widget.width()) self.setTextMargins(margin) self._main_layout.addWidget(widget) self._prefix_widget = widget return widget def search(self): """ Adds a search icon button for line edit :return: self """ prefix_btn = buttons.BaseToolButton().image('search').icon_only() suffix_btn = buttons.BaseToolButton().image('close').icon_only() suffix_btn.clicked.connect(self.clear) self.set_prefix_widget(prefix_btn) self.set_suffix_widget(suffix_btn) self.setPlaceholderText('Enter keyword to search ...') return self def search_engine(self, text='Search'): """ Adds a search push button to line edit :param text: str :return: self """ _suffix_btn = buttons.BaseButton(text).primary() _suffix_btn.clicked.connect(self.returnPressed) _suffix_btn.setFixedWidth(100) self.set_suffix_widget(_suffix_btn) self.setPlaceholderText('Enter keyword to search ...') return self def file(self, filters=None): """ Adds a ClickBrowserFileToolButton to line edit :param filters: :return: self """ _suffix_btn = browser.ClickBrowserFileToolButton() _suffix_btn.fileChanged.connect(self.setText) _suffix_btn.filters = filters self.textChanged.connect(_suffix_btn.set_path) self.set_suffix_widget(_suffix_btn) self.setPlaceholderText('Click button to browse files') return self def save_file(self, filters=None): """ Adds a ClickSaveFileToolButton to line edit :param filters: :return: self """ _suffix_button = browser.ClickSaveFileToolButton() _suffix_button.fileChanged.connect(self.setText) _suffix_button.filters = filters or list() self.textChanged.connect(_suffix_button.set_path) self.set_suffix_widget(_suffix_button) self.setPlaceholderText('Click button to set save file') return self def folder(self): """ Adds a ClickBrowserFileToolButton to line edit :return: self """ _suffix_btn = browser.ClickBrowserFolderToolButton() _suffix_btn.folderChanged.connect(self.setText) self.textChanged.connect(_suffix_btn.set_path) self.set_suffix_widget(_suffix_btn) self.setPlaceholderText('Click button to browse folder') return self def error(self): """ Shows error in line edit with red style :return: self """ def _on_show_detail(self): dlg = QTextEdit(self) dlg.setReadOnly(True) geo = QApplication.desktop().screenGeometry() dlg.setGeometry(geo.width() / 2, geo.height() / 2, geo.width() / 4, geo.height() / 4) dlg.setWindowTitle('Error Detail Information') dlg.setText(self.property('history')) dlg.setWindowFlags(Qt.Dialog) dlg.show() self.setProperty('theme_type', 'error') self.setReadOnly(True) _suffix_btn = buttons.BaseToolButton().image( 'delete_message').icon_only() _suffix_btn.clicked.connect(partial(_on_show_detail, self)) self.set_suffix_widget(_suffix_btn) self.setPlaceholderText('Error information will be here ...') return self def tiny(self): """ Sets line edit to tiny size """ widget_theme = self.theme() self.theme_size = widget_theme.tiny if widget_theme else theme.Theme.Sizes.TINY return self def small(self): """ Sets line edit to small size """ widget_theme = self.theme() self.theme_size = widget_theme.small if widget_theme else theme.Theme.Sizes.SMALL return self def medium(self): """ Sets line edit to medium size """ widget_theme = self.theme() self.theme_size = widget_theme.medium if widget_theme else theme.Theme.Sizes.MEDIUM return self def large(self): """ Sets line edit to large size """ widget_theme = self.theme() self.theme_size = widget_theme.large if widget_theme else theme.Theme.Sizes.LARGE return self def huge(self): """ Sets line edit to huge size """ widget_theme = self.theme() self.theme_size = widget_theme.huge if widget_theme else theme.Theme.Sizes.HUGE return self def password(self): """ Sets line edit password mode """ self.setEchoMode(QLineEdit.Password) return self # ================================================================================================================= # CALLBACKS # ================================================================================================================= def _on_delay_text_changed(self): """ Internal callback function that is called when delay timer is completed """ self.delayTextChanged.emit(self.text())