Skip to content

utils

clear_layout(layout)

Recursively deletes child QWidgets in the initial QLayout and in sub-layouts.

This function handles all types of QLayout subclasses (QVBoxLayout, QHBoxLayout, QGridLayout, etc.) and safely deletes all child widgets while maintaining the integrity of the parent layout structure.

Parameters:

Name Type Description Default
layout

QLayout instance to clear

required
Source code in client/ayon_ui_qt/utils.py
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
def clear_layout(layout):
    """Recursively deletes child QWidgets in the initial QLayout and in sub-layouts.

    This function handles all types of QLayout subclasses (QVBoxLayout, QHBoxLayout,
    QGridLayout, etc.) and safely deletes all child widgets while maintaining the
    integrity of the parent layout structure.

    Args:
        layout: QLayout instance to clear
    """
    if layout is None:
        return

    # print(f"layout = {layout}")

    # Work backwards through the layout to avoid index issues when removing items
    for i in reversed(range(layout.count())):
        item = layout.takeAt(i)
        if item is None:
            continue

        widget = item.widget()
        sub_layout = item.layout()

        if widget:
            # Recursively clear any layouts this widget might have
            # (in case it's a container widget with its own layouts)
            if hasattr(widget, "layout") and widget.layout():
                clear_layout(widget.layout())
            # Delete the widget
            widget.setParent(None)
            widget.deleteLater()
        elif sub_layout:
            # Recursively clear the sub-layout
            clear_layout(sub_layout)
            # Delete the layout
            sub_layout.deleteLater()

process_activity_data(activity_data, project_data)

Preprocesses payload data to extract and parse comment activities.

This function processes the input data to extract activities, specifically focusing on comment activities. It parses these activities using the AYComment class and returns a list of parsed comment objects.

Parameters:

Name Type Description Default
activity_data dict

The input data containing project activities in a specific structure. Expected to have a nested structure with 'project' -> 'activities'.

required

Returns:

Name Type Description
list list[CommentModel | VersionPublishModel | StatusChangeModel]

A list of parsed comment objects. Returns an empty list if no activities are found or if there's an error during processing.

Source code in client/ayon_ui_qt/utils.py
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
def process_activity_data(
    activity_data: dict, project_data: ProjectData
) -> list[CommentModel | VersionPublishModel | StatusChangeModel]:
    """Preprocesses payload data to extract and parse comment activities.

    This function processes the input data to extract activities, specifically
    focusing on comment activities. It parses these activities using the
    AYComment class and returns a list of parsed comment objects.

    Args:
        activity_data (dict): The input data containing project activities in
            a specific structure. Expected to have a nested structure with
            'project' -> 'activities'.
        project_data (ProjectData)

    Returns:
        list: A list of parsed comment objects. Returns an empty list if
            no activities are found or if there's an error during processing.
    """
    try:
        activities: list[dict] = activity_data["project"]["activities"]
    except KeyError as err:
        logger.error(f"Could not extract activities: {err}")
        return []

    users = {d.short_name: d for d in project_data.users}
    category_colors = {c.name: c.color for c in project_data.comment_category}

    ui_data = []
    nothing = "n/a"
    for act in activities:
        act_data = act.get("activityData", {})
        if isinstance(act_data, str):
            act_data = json.loads(act_data)
            act["activityData"] = act_data

        activity_type = act.get("activityType", "")
        activity_id = act["activityId"]

        user_name = act.get("author", {}).get("name", nothing)
        user_full_name = user_name
        user = users.get(user_name)
        if user:
            user_full_name = user.full_name

        date = act.get("updatedAt", nothing)

        if activity_type == "comment":
            annotation_models, ranges = _parse_annotations(act_data, nothing)
            file_models = _parse_files(act, ranges, nothing)
            category = act_data.get("category", "")
            ui_data.append(
                CommentModel(
                    activity_id=activity_id,
                    user_full_name=user_full_name,
                    user_name=user_name,
                    comment=act.get("body", nothing),
                    comment_date=date,
                    category=category,
                    category_color=category_colors.get(category, ""),
                    files=file_models,
                    annotations=annotation_models,
                )
            )
        elif activity_type == "version.publish":
            ui_data.append(
                VersionPublishModel(
                    activity_id=activity_id,
                    user_full_name=user_full_name,
                    user_name=user_name,
                    version=str(
                        act_data.get("origin", {}).get("name", nothing)
                    ),
                    product=str(
                        act_data.get("context", {}).get("productName", nothing)
                    ),
                    date=date,
                )
            )
        elif activity_type == "status.change":
            version = act_data.get("origin", {}).get("name", nothing)
            parents: list[dict] = act_data.get("parents", {})
            product = next(
                (p["name"] for p in parents if p["type"] == "product"),
                nothing,
            )
            ui_data.append(
                StatusChangeModel(
                    activity_id=activity_id,
                    user_full_name=user_full_name,
                    user_name=user_name,
                    product=product,
                    version=version,
                    old_status=str(act_data.get("oldValue", nothing)),
                    new_status=str(act_data.get("newValue", nothing)),
                    date=date,
                )
            )

    return ui_data