ayon-ui-qt is Qt widget library addon for AYON, designed to override Qt stylesheets of host
applications and preserve our UIs appearance.
It provides AYON-styled widgets, data models, and utility components for building consistent desktop tools.
Most widgets use variants that can be defined and tweaked in ayon_style.json.
ayon-ui-qt packages reusable UI building blocks that mirror AYON's visual
language while staying native to Qt. It includes:
- A custom
QStyleimplementation (AYONStyle) and style helpers - Component widgets (buttons, form controls, containers, cards, filters)
- Data-driven views and models for paginated tables and lazy trees
- Async task queue utilities for non-blocking model/view updates
- Added/expanded advanced data components:
PaginatedTableModelwith async fetch, sorting, tree mode, and optional event-loop batch fetching viafetch_page_batchAYTableViewsupport for persistent editor widgets throughTableColumn.widget_factoryLazyTreeModelfor async on-demand tree loading
- Added richer filtering/tagging and selection components:
AYFilter,AYFilterByCategory,AYTableFilter,AYTagSelector
- Added more view widgets and helpers:
AYCardView,AYGalleryDialog,AYFilterableList,AYSlicer
- Async infrastructure and monitoring:
AsyncTaskQueueandAsyncTaskQueueMonitor
-
Build the addon package:
python create_package.py
-
Upload the generated zip package from
dist/to your AYON server. -
Enable the addon in AYON Studio Settings.
uv sync
uv run pytestPython requirement: >=3.9.1,<3.10
from qtpy.QtWidgets import QApplication
from ayon_ui_qt.style import get_ayon_style, style_widget_and_siblings
from ayon_ui_qt.components.buttons import AYButton
from ayon_ui_qt.components.container import AYContainer
from ayon_ui_qt.components.label import AYLabel
app = QApplication([])
app.setStyle(get_ayon_style())
container = AYContainer(
layout=AYContainer.Layout.VBox,
variant=AYContainer.Variants.Low,
layout_margin=10,
layout_spacing=8,
)
container.add_widget(
AYButton("Run", variant=AYButton.Variants.Filled, icon="play_arrow")
)
container.add_widget(
AYLabel("Ready", icon="check_circle", icon_color="#60c689")
)
style_widget_and_siblings(container)
container.show()
app.exec()PaginatedTableModel expects a page fetch callback with this signature:
def fetch_page(
page: int,
page_size: int,
sort_key: str | None,
descending: bool,
parent_id: str | None,
) -> list[dict]:
...Optional batch callback (tree mode child fetches):
from ayon_ui_qt.components.table_model import BatchFetchRequest
def fetch_page_batch(
requests: list[BatchFetchRequest],
) -> dict[str | None, list[dict]]:
...Notes:
- Root-level fetch uses
fetch_page - Child-node fetches can be coalesced per event-loop tick using
fetch_page_batch - Use
reset_data()when external context changes (project/folder/filter)
| Module | Main classes |
|---|---|
buttons.py |
AYButton, AYButtonMenu |
check_box.py |
AYCheckBox |
combo_box.py |
AYComboBox, AYComboBoxModel |
line_edit.py |
AYLineEdit |
text_edit.py |
AYTextEdit |
text_box.py |
AYTextBox, AYTextEditor |
label.py |
AYLabel |
frame.py |
AYFrame |
container.py |
AYContainer |
scroll_area.py |
AYScrollArea, AYScrollBar |
| Module | Main classes |
|---|---|
table_model.py |
PaginatedTableModel, TableColumn, BatchFetchRequest |
table_view.py |
AYTableView, AYTableHeader |
table_filter.py |
AYTableFilter, AYTableFilterProxyModel |
tree_model.py |
LazyTreeModel, TreeNode |
tree_view.py |
AYTreeView |
card_view.py |
AYCardView |
| Module | Main classes |
|---|---|
entity_card.py |
AYEntityCard |
entity_path.py |
AYEntityPath, AYEntityPathSegment |
entity_thumbnail.py |
AYEntityThumbnail |
comment.py |
AYComment and related comment widgets |
comment_completion.py |
Comment completion helpers |
gallery_dialog.py |
AYGalleryDialog |
user_image.py |
AYUserImage |
| Module | Main classes |
|---|---|
filter.py |
AYFilter, AYFilterByCategory, FilterItem |
filterable_list.py |
AYFilterableList |
tag.py |
AYTag |
tag_selector.py |
AYTagSelector, TagData |
slicer.py |
AYSlicer |
dropdown.py |
AYDropdownPopup |
| Module | Main classes |
|---|---|
layouts.py |
AYHBoxLayout, AYVBoxLayout, AYGridLayout, AYFlowLayout |
task_queue.py |
AsyncTaskQueue, AsyncTask, queue helpers |
task_queue_monitor.py |
AsyncTaskQueueMonitor |
qss_override.py |
QSS/style event filter helpers |
checkbox_handler.py |
Checkbox event/data helpers |
screenshot_capture.py |
Widget screenshot capture helpers |
ayon-ui-qt/
├── client/
│ └── ayon_ui_qt/
│ ├── __init__.py
│ ├── addon.py
│ ├── style.py
│ ├── variants.py
│ ├── components/
│ ├── resources/
│ └── vendor/
├── server/
│ └── __init__.py
├── package.py
├── create_package.py
├── pyproject.toml
├── TESTING.md
└── README.md
- Install dependencies:
uv sync - Run tests:
uv run pytest - Run a single test:
uv run pytest tests/<file>::<test> -v - Format:
uv run ruff format <file> - Lint:
uv run ruff check <file>
Detailed visual testing workflow is documented in TESTING.md.
The concept of variants is borrowed from AYON's REACT library. A variant is a version of a component with a different appearance. They act like preset stylesheets.
Variants are defined in 2 files:
ayon_style.json- defines the styles for each variant- This file contains:
- global settings like the base font or the style's palette.
- Per base class variants to modify the appearance of the component.
- This file contains:
variants.py- defines the variants and their properties- This file contains enums reflecting all available variants from
ayon_style.json. - The enums can be automatically updated by running
variants.py. The code in__main__will readayon_style.jsonand update the enums if need be. It will also print a summary of the changes.
- This file contains enums reflecting all available variants from
Important
Always run variants.py after modifying ayon_style.json to ensure the enums are up to date.
Apache-2.0