Module QFlow.components
Sub-modules
QFlow.components.dialogQFlow.components.notifyQFlow.components.toggleSwitch
Classes
class Dialog (*args, **kwargs)-
Expand source code
@style(STYLE_PATH, True) class Dialog(QFrame): """ Represents a floating dialog window. This class creates a centered pop-up dialog with an optional backdrop. It supports adding widgets dynamically and adjusting its size. """ def __init__( self, parent, childrenLayout: QVBoxLayout | QHBoxLayout = None, color: str = 'white', fixedSize: list[int] = [300, 200], backdrop: str = 'background-color: rgba(0, 0, 0, 0.5);' ): """ Initializes a Dialog object. Args: parent (QWidget): The parent widget where the dialog will appear. It's usually the window. childrenLayout (QVBoxLayout | QHBoxLayout, optional): The layout to add as children. Default is None. color (str, optional): The theme color. Default is 'white'. fixedSize (list, optional): The fixed size of the dialog [width, height]. Default is [300, 200]. backdrop (str, optional): CSS style for the backdrop overlay. Default is a semi-transparent black. """ super().__init__(parent) self.setObjectName(STYLE_THEME_COLOR[color]['floatingDialog']) self.backdrop = QFrame(parent) self.backdrop.setStyleSheet(backdrop) self.backdrop.setGeometry(0, 0, parent.width(), parent.height()) self.backdrop.hide() self.backdrop.mousePressEvent = self.close self.childrenLayout = childrenLayout self.fixedSize = fixedSize self.setFixedSize(*self.fixedSize) self.mainLayout = QVBoxLayout(self) if self.childrenLayout is not None: self.mainLayout.addLayout(self.childrenLayout) self.hide() def addWidget(self, widget: QWidget) -> None: """ Adds a widget to the dialog. Args: widget (QWidget): The widget to add to the dialog. """ self.mainLayout.addWidget(widget) def addLayout(self, layout: QHBoxLayout | QVBoxLayout) -> None: """ Adds a layout to the dialog. Args: layout (QHBoxLayout | QVBoxLayout): The layout to add to the dialog. """ self.mainLayout.addLayout(layout) def show(self) -> None: """ Displays the dialog, centering it relative to its parent. """ if self.parent(): w, h = self.parent().width(), self.parent().height() self.move((w - self.width()) // 2, (h - self.height()) // 2) self.backdrop.setGeometry(0, 0, w, h) self.backdrop.show() self.backdrop.raise_() self.raise_() super().show() # Close uses event, but doesn't need it def close(self, event=None) -> None: """ Closes the dialog and hides the backdrop. """ self.backdrop.hide() self.hide()Represents a floating dialog window.
This class creates a centered pop-up dialog with an optional backdrop. It supports adding widgets dynamically and adjusting its size.
Initializes the decorated class and applies the stylesheet.
Args
*args- Positional arguments passed to the original class initializer.
**kwargs- Keyword arguments passed to the original class initializer.
Ancestors
- PyQt6.QtWidgets.QFrame
- PyQt6.QtWidgets.QWidget
- PyQt6.QtCore.QObject
- PyQt6.sip.wrapper
- PyQt6.QtGui.QPaintDevice
- PyQt6.sip.simplewrapper
Methods
def addLayout(self, layout: PyQt6.QtWidgets.QHBoxLayout | PyQt6.QtWidgets.QVBoxLayout) ‑> None-
Expand source code
def addLayout(self, layout: QHBoxLayout | QVBoxLayout) -> None: """ Adds a layout to the dialog. Args: layout (QHBoxLayout | QVBoxLayout): The layout to add to the dialog. """ self.mainLayout.addLayout(layout)Adds a layout to the dialog.
Args
layout:QHBoxLayout | QVBoxLayout- The layout to add to the dialog.
def addWidget(self, widget: PyQt6.QtWidgets.QWidget) ‑> None-
Expand source code
def addWidget(self, widget: QWidget) -> None: """ Adds a widget to the dialog. Args: widget (QWidget): The widget to add to the dialog. """ self.mainLayout.addWidget(widget)Adds a widget to the dialog.
Args
widget:QWidget- The widget to add to the dialog.
def close(self, event=None) ‑> None-
Expand source code
def close(self, event=None) -> None: """ Closes the dialog and hides the backdrop. """ self.backdrop.hide() self.hide()Closes the dialog and hides the backdrop.
def show(self) ‑> None-
Expand source code
def show(self) -> None: """ Displays the dialog, centering it relative to its parent. """ if self.parent(): w, h = self.parent().width(), self.parent().height() self.move((w - self.width()) // 2, (h - self.height()) // 2) self.backdrop.setGeometry(0, 0, w, h) self.backdrop.show() self.backdrop.raise_() self.raise_() super().show()Displays the dialog, centering it relative to its parent.
class Notify (*args, **kwargs)-
Expand source code
@style(STYLE_PATH, True) class Notify(QWidget): """ Represents an on-screen notification within a parent window. This class allows displaying messages with different notification types (success, error, info) and customizable styles. It also includes a progress bar indicating the notification duration. """ cont = {} """Dictionary tracking the number of notifications per parent window.""" def __init__( self, message: str, duration: int = 3000, delay: int = 0, parent=None, type: str = 'success', color: str = 'black', customIcon: QPixmap = None, notificationsLimit: int = 7, characterLimit: int = 60, position: str = 'top-right', items: List[QWidget] = None, opacity: float = 1.0, animatedEvents: Dict[str, bool] = {}, animationValues: Dict[str, float] = {}, autoShow: bool = True ): """ Initializes a Notify object. Args: message (str): The notification message. duration (int, optional): Duration before the notification disappears (in milliseconds). Default is 3000ms. delay (int, optional): Delay before showing the notification (in milliseconds). Default is 0ms. parent (QWidget, optional): The parent widget where the notification will be displayed. It's usually the window. type (str, optional): The type of notification ('success', 'error', 'info'). Default is 'success'. color (str, optional): The theme color ('black' or 'white'). Default is 'black'. customIcon (QPixmap, optional): A custom icon to use instead of the default. notificationsLimit (int, optional): Parent notification limiter. Default is 7. characterLimit (int, optional): Character limit in the notification. Default is 60. position (str, optional): Position of the notification ('top-right', 'top-left', 'bottom-right', 'bottom-left'). Default is 'top-right'. items (List[QWidget], optional): Widgets to add to the notification. Default is None. opacity: (float, optional): The opacity of the notify. animatedEvents: (Dict[str, bool], optional): Default animations for events to {'fadeIn': True, 'fadeOut': True}. animationValues: (Dict[str, bool], optional): Default values for animations {'opacityIncreasedIn': 0.05, 'opacityReductionOut': 0.05}. autoShow: (bool, optional): Whether to show the notification automatically after creation. Default is True. """ super().__init__(parent) self.parent = parent self.duration = duration self.delay = delay self.elapsedTime = 0 self.message = message self.position = position self.items = items self.opacity = opacity self.msRenderTime = 16 self.isVisible = False self.isShown = False self.autoShow = autoShow self.notificationsLimit = notificationsLimit self._animationValues = { 'opacityIncreasedIn': 0.05, 'opacityReductionOut': 0.05 } self._animationValues.update(animationValues) self._animatedEvents = { 'fadeIn': True, 'fadeOut': True } self._animatedEvents.update(animatedEvents) if len(message) > characterLimit: self.message = message[:characterLimit - 1] + '...' self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.Tool) self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) self.container = QFrame(self) self.container.setMinimumWidth(270) self.container.setMaximumWidth(self.parent.width()) if color in STYLE_THEME_COLOR: self.containerStyle = STYLE_THEME_COLOR[color]['QFrame'] else: raise KeyError(f"The color does not exist in Notify: '{color}'") self.container.setObjectName(self.containerStyle) self.iconLabel = QLabel(self.container) if type in ICONS: self.icon = ICONS[type]() if customIcon is not None: self.icon = customIcon self.iconLabel.setPixmap(self.icon) self.messageLabel = QLabel(self.message, self.container) if color in STYLE_THEME_COLOR: self.messageLabel.setObjectName(STYLE_THEME_COLOR[color]['QLabel']) else: raise KeyError(f"The color does not exist in Notify: '{color}'") self.progressBar = QProgressBar(self.container) if type in STYLE_BAR: self.progressBarStyle = STYLE_BAR[type] else: raise KeyError(f"The type does not exist in Notify: '{type}'") self.progressBar.setObjectName(self.progressBarStyle) self.progressBar.setFixedHeight(10) self.progressBar.setTextVisible(False) self.progressBar.setMaximum(self.duration) self.progressBar.setValue(0) self.contentLayout = QHBoxLayout() self.contentLayout.setContentsMargins(0, 0, 0, 0) self.contentLayout.setSpacing(8) self.contentLayout.addWidget(self.iconLabel, 0, Qt.AlignmentFlag.AlignVCenter) self.contentLayout.addWidget(self.messageLabel, 1, Qt.AlignmentFlag.AlignVCenter) self.containerLayout = QVBoxLayout(self.container) self.containerLayout.addLayout(self.contentLayout) self.containerLayout.addWidget(self.progressBar) if self.items is not None: for widget in items: if isinstance(widget, QWidget): self.containerLayout.addWidget(widget) self.containerLayout.setContentsMargins(20, 10, 20, 10) self.container.setLayout(self.containerLayout) self.container.adjustSize() # Check notification limit before incrementing counter if self.parent in Notify.cont: if Notify.cont[self.parent] >= notificationsLimit: self.limitExceeded = True return # Don't create notification if limit exceeded else: Notify.cont[self.parent] = 0 self.limitExceeded = False self.mainLayout = QVBoxLayout(self) self.mainLayout.addWidget(self.container) self.mainLayout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.mainLayout) self.adjustSize() # Initialize timers but don't start them yet self.positionTimer = QTimer(self) self.positionTimer.timeout.connect(self.updatePosition) self.timer = QTimer(self) self.timer.timeout.connect(self.updateProgress) # Handle auto-show behavior if self.autoShow: self.show() def show(self) -> None: """Shows the notification. Can be called manually to control when the notification appears.""" if self.isShown or self.limitExceeded: return # Don't show if already shown or limit exceeded self.isShown = True # Handle delay if self.delay > 0: # Schedule the notification to show after delay QTimer.singleShot(self.delay, self._showNotification) else: # Show immediately if no delay self._showNotification() def _showNotification(self) -> None: """Shows the notification after the delay period.""" # Increment counter only when actually showing Notify.cont[self.parent] += 1 self.notificationCount = Notify.cont[self.parent] self.updatePosition() # Start timers self.positionTimer.start(self.msRenderTime) # Approximately 60 fps self.timer.start(self.msRenderTime) # Approximately 60 fps # Schedule auto-close QTimer.singleShot(self.duration, self.close) # Set opacity if self.opacity != 1.0: self.setWindowOpacity(self.opacity) # Handle fade-in animation if self._animatedEvents['fadeIn']: self._animateFadeIn() # Mark as visible and show self.isVisible = True super().show() # Call the parent's show method def _animateFadeOut(self) -> None: timer = QTimer(self) opacity = self.windowOpacity() def _modifyOpacity(): nonlocal opacity opacity -= self._animationValues['opacityReductionOut'] if opacity <= 0.1: timer.stop() self.setWindowOpacity(opacity) timer.timeout.connect(_modifyOpacity) timer.start(self.msRenderTime) def _animateFadeIn(self) -> None: self.setWindowOpacity(0.1) timer = QTimer(self) opacity = self.windowOpacity() def _modifyOpacity(): nonlocal opacity opacity += self._animationValues['opacityIncreasedIn'] if opacity >= self.opacity: timer.stop() self.setWindowOpacity(opacity) timer.timeout.connect(_modifyOpacity) timer.start(self.msRenderTime) def updatePosition(self) -> None: """Updates the notification's position relative to its parent window based on the specified position.""" if self.parent: if not self.parent.isVisible(): self.close() margin = 20 betweenMargin = 20 notificationHeight = self.height() + betweenMargin if 'right' in self.position: x = self.parent.x() + self.parent.width() - self.width() - margin else: x = self.parent.x() + margin if 'top' in self.position: y = self.parent.y() + 40 + (self.notificationCount - 1) * notificationHeight else: y = (self.parent.y() + self.parent.height() - self.notificationCount * notificationHeight) self.move(x, y) def updateProgress(self) -> None: """Updates the progress bar and closes the notification when the duration ends.""" self.elapsedTime += 30 self.progressBar.setValue(self.elapsedTime) if self.elapsedTime >= self.duration: self.timer.stop() if self._animatedEvents['fadeOut']: self._animateFadeOut() QTimer.singleShot(200, self.close) else: self.close() def hide(self) -> None: """Hides the notification without closing it.""" if self.isVisible: super().hide() self.isVisible = False if self.positionTimer.isActive(): self.positionTimer.stop() if self.timer.isActive(): self.timer.stop() def isNotificationVisible(self) -> bool: """Returns True if the notification is currently visible.""" return self.isVisible def isNotificationShown(self) -> bool: """Returns True if show() has been called on this notification.""" return self.isShown def close(self) -> None: """Closes the notification and updates the notification count.""" if self.isVisible and self.parent in Notify.cont and Notify.cont[self.parent] > 0: Notify.cont[self.parent] -= 1 super().close()Represents an on-screen notification within a parent window.
This class allows displaying messages with different notification types (success, error, info) and customizable styles. It also includes a progress bar indicating the notification duration.
Initializes the decorated class and applies the stylesheet.
Args
*args- Positional arguments passed to the original class initializer.
**kwargs- Keyword arguments passed to the original class initializer.
Ancestors
- PyQt6.QtWidgets.QWidget
- PyQt6.QtCore.QObject
- PyQt6.sip.wrapper
- PyQt6.QtGui.QPaintDevice
- PyQt6.sip.simplewrapper
Class variables
var cont-
Dictionary tracking the number of notifications per parent window.
Methods
def close(self) ‑> None-
Expand source code
def close(self) -> None: """Closes the notification and updates the notification count.""" if self.isVisible and self.parent in Notify.cont and Notify.cont[self.parent] > 0: Notify.cont[self.parent] -= 1 super().close()Closes the notification and updates the notification count.
def hide(self) ‑> None-
Expand source code
def hide(self) -> None: """Hides the notification without closing it.""" if self.isVisible: super().hide() self.isVisible = False if self.positionTimer.isActive(): self.positionTimer.stop() if self.timer.isActive(): self.timer.stop()Hides the notification without closing it.
def isNotificationShown(self) ‑> bool-
Expand source code
def isNotificationShown(self) -> bool: """Returns True if show() has been called on this notification.""" return self.isShownReturns True if show() has been called on this notification.
def isNotificationVisible(self) ‑> bool-
Expand source code
def isNotificationVisible(self) -> bool: """Returns True if the notification is currently visible.""" return self.isVisibleReturns True if the notification is currently visible.
def show(self) ‑> None-
Expand source code
def show(self) -> None: """Shows the notification. Can be called manually to control when the notification appears.""" if self.isShown or self.limitExceeded: return # Don't show if already shown or limit exceeded self.isShown = True # Handle delay if self.delay > 0: # Schedule the notification to show after delay QTimer.singleShot(self.delay, self._showNotification) else: # Show immediately if no delay self._showNotification()Shows the notification. Can be called manually to control when the notification appears.
def updatePosition(self) ‑> None-
Expand source code
def updatePosition(self) -> None: """Updates the notification's position relative to its parent window based on the specified position.""" if self.parent: if not self.parent.isVisible(): self.close() margin = 20 betweenMargin = 20 notificationHeight = self.height() + betweenMargin if 'right' in self.position: x = self.parent.x() + self.parent.width() - self.width() - margin else: x = self.parent.x() + margin if 'top' in self.position: y = self.parent.y() + 40 + (self.notificationCount - 1) * notificationHeight else: y = (self.parent.y() + self.parent.height() - self.notificationCount * notificationHeight) self.move(x, y)Updates the notification's position relative to its parent window based on the specified position.
def updateProgress(self) ‑> None-
Expand source code
def updateProgress(self) -> None: """Updates the progress bar and closes the notification when the duration ends.""" self.elapsedTime += 30 self.progressBar.setValue(self.elapsedTime) if self.elapsedTime >= self.duration: self.timer.stop() if self._animatedEvents['fadeOut']: self._animateFadeOut() QTimer.singleShot(200, self.close) else: self.close()Updates the progress bar and closes the notification when the duration ends.
class ToggleSwitch (parent,
width: int = 50,
height: int = 25,
bgColor: list[str] = ['#ccc', '#00c853'],
circleColor: str = '#fff',
checked: bool = False)-
Expand source code
class ToggleSwitch(QWidget): """ Represents a custom animated toggle switch. This widget mimics a modern switch with animation and customizable colors. The circle smoothly slides between ON and OFF states upon click, and emits visual feedback based on the internal boolean state. """ def __init__( self, parent, width: int = 50, height: int = 25, # num ≠ 0 ⇔ True: It's the same as on or off bgColor: list[str] = ['#ccc', '#00c853'], circleColor: str = '#fff', checked: bool = False ): """ Initializes the ToggleSwitch object. Args: parent (QWidget): The parent widget. width (int, optional): The width of the toggle. Default is 50. height (int, optional): The height of the toggle. Default is 25. bgColor (list, optional): List of two colors [offColor, onColor] in hex format. circleColor (str, optional): Color of the sliding circle in hex format. """ super().__init__(parent) self.setFixedSize(width, height) self._checked = False self._circlePosition = 2 self._animation = QPropertyAnimation(self, b"circlePosition") self._animation.setDuration(150) self._bgColorOn = QColor(bgColor[1]) self._bgColorOff = QColor(bgColor[0]) self._circleColor = QColor(circleColor) self.setChecked(checked) self.setCursor(QCursor(Qt.CursorShape.PointingHandCursor)) def mousePressEvent(self, event): """ Handles the mouse press event to toggle the switch state. Args: event (QMouseEvent): The mouse event. """ self._checked = not self._checked self._animate() self.update() super().mousePressEvent(event) def _animate(self): """ Performs the circle sliding animation based on the current state. """ start = self._circlePosition end = self.width() - self.height() + 2 if self._checked else 2 self._animation.stop() self._animation.setStartValue(start) self._animation.setEndValue(end) self._animation.start() def paintEvent(self, event): """ Paints the switch background and sliding circle. Args: event (QPaintEvent): The paint event. """ painter = QPainter(self) painter.setRenderHint(QPainter.RenderHint.Antialiasing) bg_color = self._bgColorOn if self._checked else self._bgColorOff painter.setBrush(QBrush(bg_color)) painter.setPen(Qt.PenStyle.NoPen) painter.drawRoundedRect(0, 0, self.width(), self.height(), self.height() / 2, self.height() / 2) painter.setBrush(QBrush(self._circleColor)) painter.drawEllipse(self._circlePosition, 2, self.height() - 4, self.height() - 4) def isChecked(self): """ Returns: bool: The current checked state of the switch. """ return self._checked def setChecked(self, checked: bool): """ Sets the checked state of the switch and updates its position immediately. Args: checked (bool): The desired checked state. """ self._checked = checked self._animate() self.update() def getCirclePosition(self): """ Returns: int: The current X position of the circle. """ return self._circlePosition def setCirclePosition(self, pos): """ Updates the X position of the circle (used by the animation). Args: pos (int): The new position. """ self._circlePosition = pos self.update() circlePosition = Property(int, fget=getCirclePosition, fset=setCirclePosition)Represents a custom animated toggle switch.
This widget mimics a modern switch with animation and customizable colors. The circle smoothly slides between ON and OFF states upon click, and emits visual feedback based on the internal boolean state.
Initializes the ToggleSwitch object.
Args
parent:QWidget- The parent widget.
width:int, optional- The width of the toggle. Default is 50.
height:int, optional- The height of the toggle. Default is 25.
bgColor:list, optional- List of two colors [offColor, onColor] in hex format.
circleColor:str, optional- Color of the sliding circle in hex format.
Ancestors
- PyQt6.QtWidgets.QWidget
- PyQt6.QtCore.QObject
- PyQt6.sip.wrapper
- PyQt6.QtGui.QPaintDevice
- PyQt6.sip.simplewrapper
Instance variables
var circlePosition-
pyqtProperty(type, fget=None, fset=None, freset=None, fdel=None, doc=None, designable=True, scriptable=True, stored=True, user=False, constant=False, final=False, notify=None, revision=0) -> property attribute
type is the type of the property. It is either a type object or a string that is the name of a C++ type. freset is a function for resetting an attribute to its default value. designable sets the DESIGNABLE flag (the default is True for writable properties and False otherwise). scriptable sets the SCRIPTABLE flag. stored sets the STORED flag. user sets the USER flag. constant sets the CONSTANT flag. final sets the FINAL flag. notify is the NOTIFY signal. revision is the REVISION. The other parameters are the same as those required by the standard Python property type. Properties defined using pyqtProperty behave as both Python and Qt properties. Decorators can be used to define new properties or to modify existing ones.
Methods
def getCirclePosition(self)-
Expand source code
def getCirclePosition(self): """ Returns: int: The current X position of the circle. """ return self._circlePositionReturns
int- The current X position of the circle.
def isChecked(self)-
Expand source code
def isChecked(self): """ Returns: bool: The current checked state of the switch. """ return self._checkedReturns
bool- The current checked state of the switch.
def mousePressEvent(self, event)-
Expand source code
def mousePressEvent(self, event): """ Handles the mouse press event to toggle the switch state. Args: event (QMouseEvent): The mouse event. """ self._checked = not self._checked self._animate() self.update() super().mousePressEvent(event)Handles the mouse press event to toggle the switch state.
Args
event:QMouseEvent- The mouse event.
def paintEvent(self, event)-
Expand source code
def paintEvent(self, event): """ Paints the switch background and sliding circle. Args: event (QPaintEvent): The paint event. """ painter = QPainter(self) painter.setRenderHint(QPainter.RenderHint.Antialiasing) bg_color = self._bgColorOn if self._checked else self._bgColorOff painter.setBrush(QBrush(bg_color)) painter.setPen(Qt.PenStyle.NoPen) painter.drawRoundedRect(0, 0, self.width(), self.height(), self.height() / 2, self.height() / 2) painter.setBrush(QBrush(self._circleColor)) painter.drawEllipse(self._circlePosition, 2, self.height() - 4, self.height() - 4)Paints the switch background and sliding circle.
Args
event:QPaintEvent- The paint event.
def setChecked(self, checked: bool)-
Expand source code
def setChecked(self, checked: bool): """ Sets the checked state of the switch and updates its position immediately. Args: checked (bool): The desired checked state. """ self._checked = checked self._animate() self.update()Sets the checked state of the switch and updates its position immediately.
Args
checked:bool- The desired checked state.
def setCirclePosition(self, pos)-
Expand source code
def setCirclePosition(self, pos): """ Updates the X position of the circle (used by the animation). Args: pos (int): The new position. """ self._circlePosition = pos self.update()Updates the X position of the circle (used by the animation).
Args
pos:int- The new position.