dayu_widgets

repository·master·Indexed 19 days ago

https://github.com/phenom-films/dayu_widgets

A library of themed UI components for PySide2 and PySide6 applications. Inspired by AntDesign, iView, and WeChat, it provides a modern look and feel with support for both light and dark modes. The library includes a wide range of components across categories such as General (MPushButton, MLabel), Navigation (MBreadcrumb, MPage), Data Entry (MLineEdit, MSwitch), Data Display (MAvatar, MCard), and Feedback (MAlert, MToast).

Tokens
42K
Snippets
141
Records
192
Agent score
67%

What's inside dayu_widgets

  1. Overview of dayu_widgets components

    master

    dayu_widgets provides themed PySide components inspired by AntDesign, iView, and WeChat. It supports both light and dark themes, with customizable theme colors for each.

    Components are categorized as follows:

    General

    • MPushButton (inherits QPushButton)
    • MLabel (inherits QLabel)
    • MLoading (inherits QWidget)
    • MToolButton (inherits QToolButton)
    • MBreadcrumb (inherits QWidget)
    • MMenuTabWidget (inherits QWidget)
    • MPage (inherits QWidget)

    Data Entry

    • MCheckBox (inherits QCheckBox)
    • File/Folder Browsers: MClickBrowserFilePushButton, MClickBrowserFileToolButton, MClickBrowserFolderPushButton, MClickBrowserFolderToolButton, MDragFileButton, MDragFolderButton
    • MLineEdit (inherits QLineEdit)
    • MRadioButton (inherits QRadioButton)
    • MSwitch (inherits QRadioButton)
    • MSilder (inherits QSlider)
    • SpinBoxes/Date Edits: MSpinBox, MDoubleSpinBox, MDateTimeEdit, MDateEdit, MTimeEdit

    Data Display

    • MAvatar (inherits QLabel)
    • MBadge (inherits QWidget)
    • MCarousel (inherits QGraphicsView)
    • MCard (inherits QWidget)
    • MCollapse (inherits QWidget)
    • MLineTabWidget (inherits QWidget)
    • Tags: MTag (inherits QLabel), MCheckableTag (inherits QCheckBox), MNewTag (inherits QWidget)

    Feedback

    • MAlert (inherits QWidget)
    • MDrawer (inherits QWidget)
    • MMessage (inherits QWidget)
    • MProgressBar (inherits QProgressBar)
    • MProgressCircle (inherits QProgressBar)
    • MToast (inherits QWidget)

    Other

    • MDivider (inherits QWidget)
  2. Run dayu_widgets example programs

    master

    After installation, you can run the built-in example programs to explore the components. Note that a Qt environment (such as PySide2 or PyQt5) must be installed.

    There are two ways to run the examples:

    1. Using the Python module: Requires you to have PySide2 or PyQt5 already installed in your environment.
    2. Using uvx (Recommended): Automatically handles dependencies, including the Qt environment.

    If using uvx, use the --with pyside2 flag to ensure the Qt dependency is provided.

    # Using Python module (requires PySide2 or PyQt5 installed)
    python -m dayu_widgets
    
    # Using uvx (Recommended: automatically handles dependencies)
    uvx --python 3.10 --with pyside2 dayu_widgets
  3. Run the dayu_widgets demo

    master

    You can run the built-in demo application to explore the widgets. Note that a Qt environment (such as PySide2 or PyQt5) must be available.

    If you have a Qt environment installed, use the Python module command. Otherwise, it is recommended to use uvx to automatically handle the necessary Qt dependencies.

    # Option 1: Run as a Python module (requires PySide2 or PyQt5 to be installed)
    python -m dayu_widgets
    
    # Option 2: Use uvx (recommended, handles dependencies automatically)
    uvx --python 3.10 --with pyside2 dayu_widgets
  4. How MComboBoxSearchMixin enables searching

    master

    The MComboBoxSearchMixin adds search/filtering capabilities to an MComboBox. When this mixin is active, the combo box becomes editable, and typing in the text field filters the items in the model using a QSortFilterProxyModel.

    To enable searching, set the search property to True. This triggers the search() method which:

    1. Sets focus policy to StrongFocus.
    2. Makes the widget editable.
    3. Connects the textEdited signal of the line edit to the filter_model.setFilterFixedString method.
    4. Connects the completer.activated signal to update the current index based on the selected completion text.
  5. MTheme icon path management

    master

    When set_theme is called, MTheme automatically configures icon paths based on the theme mode.

    • Light Theme: Uses standard filenames (e.g., down_line.png).
    • Dark Theme: Appends _dark to filenames (e.g., down_line_dark.png).
    • SVG Icons: Always uses the .svg extension without a theme suffix.

    Available icon attributes on an MTheme instance include:

    • icon_down, icon_up, icon_left, icon_right, icon_close
    • icon_calender, icon_splitter, icon_float, icon_size_grip
    • icon_check, icon_minus, icon_circle, icon_sphere (SVG based)
  6. Manage application settings with the @wrapper decorator

    master

    The wrapper decorator provides a mechanism to automatically persist and restore widget properties (like geometry, state, or custom properties) using QSettings.

    Workflow

    1. Decorate a class: Apply @wrapper(cls, event_name="closeEvent") to your widget class.
    2. Bind properties: Inside the class, use self.bind(attr, widget, property, default=None, formatter=None) to register properties to be saved.
    3. Automatic Persistence: When the specified event_name (e.g., closeEvent) is triggered, the class automatically calls write_settings(), saving all bound properties to an .ini file.
    4. Automatic Restoration: When the class is initialized, bind reads the existing settings and applies them to the widgets.

    Key Methods

    • bind(attr, widget, property, ...): Registers a widget property for persistence.
    • unbind(attr, widget, property): Stops tracking a property.
    • write_settings(): Manually triggers the saving of all bound data.

    Special Property Handling

    • "geometry": Uses saveGeometry() and restoreGeometry().
    • "state": Uses saveState() and restoreState() (useful for QMainWindow or QSplitter).
    from qtpy import QtWidgets
    from dayu_widgets.utils import wrapper
    
    @wrapper
    class MyWindow(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
            self.central_widget = QtWidgets.QWidget()
            self.setCentralWidget(self.central_widget)
            
            # Bind the window geometry to be saved under 'window_geo'
            self.bind("window_geo", self, "geometry")
            
            # Bind a custom property of a widget
            self.my_button = QtWidgets.QPushButton("Click me", self.central_widget)
            self.bind("button_text", self.my_button, "text", default="Default Text")
    
        def closeEvent(self, event):
            # The wrapper intercepts this to call write_settings()
            super().closeEvent(event)
  7. How MMenu cascading mode works

    master

    When MMenu is initialized with cascader=True, the sig_value_changed signal behaves differently:

    • Standard Mode (cascader=False): The signal emits only the value of the specifically selected action.
    • Cascading Mode (cascader=True): The signal emits a list containing the values of all parent menus leading to the selection.

    Example: If you have a menu structure Root (val: 'r') -> Child (val: 'c'), selecting 'Child' in cascading mode will emit ['r', 'c'].

  8. MComboBox custom menu integration

    master

    You can replace the standard dropdown popup with a custom menu widget using set_menu(menu).

    When a menu is set via set_menu:

    1. The menu's sig_value_changed signal is connected to the MComboBox's sig_value_changed and set_value methods.
    2. showPopup() is overridden: instead of showing the standard QComboBox popup, it hides the default popup and calls popup() on the custom menu at the global position of the combo box.

    Note: If you call setView() on the MComboBox, it flags _has_custom_view = True, which causes showPopup() to revert to the default behavior instead of using the custom menu.

  9. Use MFieldMixin to manage form fields and data binding

    master

    MFieldMixin is a mixin designed to be added to a class (typically a form or data controller) to manage data fields, handle computed properties, and synchronize data between a data model and UI widgets.

    It distinguishes between two types of fields:

    1. Props Fields: Static values passed via a getter (which can be a direct value).
    2. Computed Fields: Dynamic values retrieved via a getter function.

    Key capabilities include:

    • Registration: Define fields using register_field.
    • Binding: Connect data fields to UI widgets using bind, allowing for automatic UI updates when data changes and data updates when user interactions occur.
    • Validation: Check if all required fields are populated using _is_complete (internal/protected).
    • Access: Retrieve or update field values using field(name) and set_field(name, value).
    class MyForm(MFieldMixin, QWidget):
        def __init__(self):
            super().__init__()
            # Register a static property
            self.register_field("username", getter="admin")
            
            # Register a computed property
            self.register_field("timestamp", getter=lambda: datetime.now().isoformat())
    
            # Bind a widget to a field
            self.bind("username", self.line_edit, "text", signal="textChanged")