diff --git a/client/ayon_core/tools/publisher/widgets/card_view_widgets.py b/client/ayon_core/tools/publisher/widgets/card_view_widgets.py index 1a2855888a..238f270f1f 100644 --- a/client/ayon_core/tools/publisher/widgets/card_view_widgets.py +++ b/client/ayon_core/tools/publisher/widgets/card_view_widgets.py @@ -23,7 +23,7 @@ from __future__ import annotations import re import collections -from typing import Dict +from typing import Optional from qtpy import QtWidgets, QtCore @@ -87,7 +87,6 @@ class BaseGroupWidget(QtWidgets.QWidget): self._group = group_name self._widgets_by_id = {} - self._ordered_item_ids = [] self._label_widget = label_widget self._content_layout = layout @@ -102,48 +101,25 @@ class BaseGroupWidget(QtWidgets.QWidget): return self._group - def get_widget_by_item_id(self, item_id): - """Get instance widget by its id.""" + def set_widgets( + self, + widgets_by_id: dict[str, QtWidgets.QWidget], + ordered_ids: list[str], + ) -> None: + self._remove_all_except(set(self._widgets_by_id)) + idx = 1 + for item_id in ordered_ids: + widget = widgets_by_id[item_id] + self._content_layout.insertWidget(idx, widget) + self._widgets_by_id[item_id] = widget + idx += 1 - return self._widgets_by_id.get(item_id) - - def get_selected_item_ids(self): - """Selected instance ids. - - Returns: - Set[str]: Instance ids that are selected. - """ - - return { - instance_id - for instance_id, widget in self._widgets_by_id.items() - if widget.is_selected - } - - def get_selected_widgets(self): - """Access to widgets marked as selected. - - Returns: - List[InstanceCardWidget]: Instance widgets that are selected. - """ - - return [ - widget - for instance_id, widget in self._widgets_by_id.items() - if widget.is_selected - ] - - def get_ordered_widgets(self): - """Get instance ids in order as are shown in ui. - - Returns: - List[str]: Instance ids. - """ - - return [ - self._widgets_by_id[instance_id] - for instance_id in self._ordered_item_ids - ] + def take_widgets(self, widget_ids: set[str]): + for widget_id in widget_ids: + widget = self._widgets_by_id.pop(widget_id) + index = self._content_layout.indexOf(widget) + if index >= 0: + self._content_layout.takeAt(index) def _remove_all_except(self, item_ids): item_ids = set(item_ids) @@ -160,149 +136,6 @@ class BaseGroupWidget(QtWidgets.QWidget): self._content_layout.removeWidget(widget) widget.deleteLater() - def _update_ordered_item_ids(self): - ordered_item_ids = [] - for idx in range(self._content_layout.count()): - if idx > 0: - item = self._content_layout.itemAt(idx) - widget = item.widget() - if widget is not None: - ordered_item_ids.append(widget.id) - - self._ordered_item_ids = ordered_item_ids - - def _on_widget_selection(self, instance_id, group_id, selection_type): - self.selected.emit(instance_id, group_id, selection_type) - - def set_active_toggle_enabled(self, enabled): - for widget in self._widgets_by_id.values(): - if isinstance(widget, InstanceCardWidget): - widget.set_active_toggle_enabled(enabled) - - -class ConvertorItemsGroupWidget(BaseGroupWidget): - def update_items(self, items_by_id): - items_by_label = collections.defaultdict(list) - for item in items_by_id.values(): - items_by_label[item.label].append(item) - - # Remove instance widgets that are not in passed instances - self._remove_all_except(items_by_id.keys()) - - # Sort instances by product name - sorted_labels = list(sorted(items_by_label.keys())) - - # Add new instances to widget - widget_idx = 1 - for label in sorted_labels: - for item in items_by_label[label]: - if item.id in self._widgets_by_id: - widget = self._widgets_by_id[item.id] - widget.update_item(item) - else: - widget = ConvertorItemCardWidget(item, self) - widget.selected.connect(self._on_widget_selection) - widget.double_clicked.connect(self.double_clicked) - self._widgets_by_id[item.id] = widget - self._content_layout.insertWidget(widget_idx, widget) - widget_idx += 1 - - self._update_ordered_item_ids() - - -class InstanceGroupWidget(BaseGroupWidget): - """Widget wrapping instances under group.""" - - active_changed = QtCore.Signal(str, str, bool) - - def __init__(self, group_icons, *args, **kwargs): - super().__init__(*args, **kwargs) - - self._group_icons = group_icons - - def update_icons(self, group_icons): - self._group_icons = group_icons - - def update_instance_values( - self, - context_info_by_id, - instance_items_by_id, - instance_ids, - parent_is_active_by_id, - ): - """Trigger update on instance widgets.""" - - for instance_id, widget in self._widgets_by_id.items(): - if instance_ids is not None and instance_id not in instance_ids: - continue - widget.update_instance( - instance_items_by_id[instance_id], - context_info_by_id[instance_id], - parent_is_active_by_id[instance_id], - ) - - def update_instances( - self, - instances: list[InstanceItem], - context_info_by_id: dict[str, InstanceContextInfo], - parent_active_by_id: dict[str, bool] - ): - """Update instances for the group. - - Args: - instances (list[InstanceItem]): List of instances in - CreateContext. - context_info_by_id (dict[str, InstanceContextInfo]): Instance - context info by instance id. - parent_active_by_id (dict[str, bool]): Instance has active parent. - - """ - # Store instances by id and by product name - instances_by_id = {} - instances_by_product_name = collections.defaultdict(list) - for instance in instances: - instances_by_id[instance.id] = instance - product_name = instance.product_name - instances_by_product_name[product_name].append(instance) - - # Remove instance widgets that are not in passed instances - self._remove_all_except(instances_by_id.keys()) - - # Sort instances by product name - sorted_product_names = list(sorted(instances_by_product_name.keys())) - - # Add new instances to widget - widget_idx = 1 - for product_names in sorted_product_names: - for instance in instances_by_product_name[product_names]: - context_info = context_info_by_id[instance.id] - parent_is_active = parent_active_by_id[instance.id] - if instance.id in self._widgets_by_id: - widget = self._widgets_by_id[instance.id] - widget.update_instance( - instance, context_info, parent_is_active - ) - else: - group_icon = self._group_icons[instance.creator_identifier] - widget = InstanceCardWidget( - instance, - context_info, - parent_is_active, - group_icon, - self - ) - widget.selected.connect(self._on_widget_selection) - widget.active_changed.connect(self._on_active_changed) - widget.double_clicked.connect(self.double_clicked) - self._widgets_by_id[instance.id] = widget - self._content_layout.insertWidget(widget_idx, widget) - widget_idx += 1 - - self._update_ordered_item_ids() - - def _on_active_changed(self, instance_id, value): - self.active_changed.emit(self.group_name, instance_id, value) - class CardWidget(BaseClickableFrame): """Clickable card used as bigger button.""" @@ -423,6 +256,10 @@ class ConvertorItemCardWidget(CardWidget): self._icon_widget = icon_widget self._label_widget = label_widget + def update_item(self, item): + self._id = item.id + self.identifier = item.identifier + class InstanceCardWidget(CardWidget): """Card widget representing instance.""" @@ -433,7 +270,7 @@ class InstanceCardWidget(CardWidget): self, instance, context_info, - parent_is_active: bool, + is_parent_active: bool, group_icon, parent: BaseGroupWidget, ): @@ -444,7 +281,7 @@ class InstanceCardWidget(CardWidget): self._id = instance.id self._group_identifier = instance.group_label self._group_icon = group_icon - self._parent_is_active = parent_is_active + self._is_parent_active = is_parent_active self._toggle_is_enabled = True self._last_product_name = None @@ -499,18 +336,26 @@ class InstanceCardWidget(CardWidget): self._active_checkbox = active_checkbox self._expand_btn = expand_btn - self._update_instance_values(context_info, parent_is_active) + self._update_instance_values(context_info, is_parent_active) - def set_active_toggle_enabled(self, enabled): + def set_active_toggle_enabled(self, enabled: bool) -> None: if self._toggle_is_enabled is enabled: return self._toggle_is_enabled = enabled self._update_checkbox_state() - @property - def is_active(self): + def is_active(self) -> bool: return self._active_checkbox.isChecked() + def is_parent_active(self) -> bool: + return self._is_parent_active + + def set_parent_active(self, is_active: bool) -> None: + if self._is_parent_active is is_active: + return + self._is_parent_active = is_active + self._update_checkbox_state() + def is_checkbox_enabled(self) -> bool: """Checkbox can be changed by user.""" return ( @@ -518,10 +363,10 @@ class InstanceCardWidget(CardWidget): and not self.instance.is_mandatory ) - def update_instance(self, instance, context_info, parent_is_active): + def update_instance(self, instance, context_info, is_parent_active): """Update instance object and update UI.""" self.instance = instance - self._update_instance_values(context_info, parent_is_active) + self._update_instance_values(context_info, is_parent_active) def _validate_context(self, context_info): valid = context_info.is_valid @@ -560,9 +405,9 @@ class InstanceCardWidget(CardWidget): QtCore.Qt.NoTextInteraction ) - def _update_instance_values(self, context_info, parent_is_active): + def _update_instance_values(self, context_info, is_parent_active): """Update instance data""" - self._parent_is_active = parent_is_active + self._is_parent_active = is_parent_active self._update_product_name() self._update_checkbox_state() self._validate_context(context_info) @@ -587,7 +432,7 @@ class InstanceCardWidget(CardWidget): def _used_parent_active(self) -> bool: parent_enabled = True if self.instance.parent_flags & ParentFlags.share_active: - parent_enabled = self._parent_is_active + parent_enabled = self._is_parent_active return parent_enabled def _set_expanded(self, expanded=None): @@ -654,11 +499,20 @@ class InstanceCardView(AbstractInstanceView): self._content_layout = content_layout self._content_widget = content_widget - self._context_widget = None - self._convertor_items_group = None - self._active_toggle_enabled = True - self._widgets_by_group: Dict[str, InstanceGroupWidget] = {} + self._active_toggle_enabled: bool = True + self._convertors_group: Optional[BaseGroupWidget] = None + self._convertor_widgets_by_id: dict[str, ConvertorItemCardWidget] = {} + self._convertor_ids: list[str] = [] + + self._group_name_by_instance_id: dict[str, str] = {} + self._instance_ids_by_group_name: dict[str, list[str]] = ( + collections.defaultdict(list) + ) self._ordered_groups = [] + self._group_icons = {} + self._context_widget: Optional[ContextCardWidget] = None + self._widgets_by_id: dict[str, InstanceCardWidget] = {} + self._widgets_by_group: dict[str, BaseGroupWidget] = {} self._instance_ids_by_parent_id = collections.defaultdict(set) @@ -694,7 +548,7 @@ class InstanceCardView(AbstractInstanceView): continue instance_id = widget.id - is_active = widget.is_active + is_active = widget.is_active() if value == -1: active_state_by_id[instance_id] = not is_active continue @@ -731,12 +585,17 @@ class InstanceCardView(AbstractInstanceView): ): output.append(self._context_widget) - if self._convertor_items_group is not None: - output.extend(self._convertor_items_group.get_selected_widgets()) + output.extend( + widget + for widget in self._convertor_widgets_by_id.values() + if widget.is_selected + ) - for group_widget in self._widgets_by_group.values(): - for widget in group_widget.get_selected_widgets(): - output.append(widget) + output.extend( + widget + for widget in self._widgets_by_id.values() + if widget.is_selected + ) return output def _get_selected_instance_ids(self): @@ -747,11 +606,17 @@ class InstanceCardView(AbstractInstanceView): ): output.append(CONTEXT_ID) - if self._convertor_items_group is not None: - output.extend(self._convertor_items_group.get_selected_item_ids()) + output.extend( + conv_id + for conv_id, widget in self._widgets_by_id.items() + if widget.is_selected + ) - for group_widget in self._widgets_by_group.values(): - output.extend(group_widget.get_selected_item_ids()) + output.extend( + widget.id + for instance_id, widget in self._widgets_by_id.items() + if widget.is_selected + ) return output def refresh(self): @@ -759,13 +624,14 @@ class InstanceCardView(AbstractInstanceView): self._make_sure_context_widget_exists() - self._update_convertor_items_group() + self._update_convertors_group() context_info_by_id = self._controller.get_instances_context_info() # Prepare instances by group and identifiers by group instances_by_group = collections.defaultdict(list) identifiers_by_group = collections.defaultdict(set) + identifiers: set[str] = set() instances_by_id = {} instance_ids_by_parent_id = collections.defaultdict(set) instance_items = self._controller.get_instance_items() @@ -775,6 +641,7 @@ class InstanceCardView(AbstractInstanceView): identifiers_by_group[group_name].add( instance.creator_identifier ) + identifiers.add(instance.creator_identifier) instances_by_id[instance.id] = instance instance_ids_by_parent_id[instance.parent_instance_id].add( instance.id @@ -787,28 +654,67 @@ class InstanceCardView(AbstractInstanceView): _queue = collections.deque() _queue.append((None, True)) while _queue: - parent_id, parent_is_active = _queue.popleft() + parent_id, is_parent_active = _queue.popleft() for instance_id in instance_ids_by_parent_id[parent_id]: instance_item = instances_by_id[instance_id] is_active = instance_item.is_active if ( - not parent_is_active + not is_parent_active and instance_item.parent_flags & ParentFlags.share_active ): is_active = False - parent_active_by_id[instance_id] = parent_is_active + parent_active_by_id[instance_id] = is_parent_active _queue.append( (instance_id, is_active) ) - self._instance_ids_by_parent_id = instance_ids_by_parent_id + # Remove groups that were not found in passed instances + groups_to_remove = ( + set(self._widgets_by_group) - set(instances_by_group) + ) - # Remove groups that were not found in apassed instances - for group_name in tuple(self._widgets_by_group.keys()): - if group_name in instances_by_group: - continue + # Sort groups + sorted_group_names = list(sorted(instances_by_group.keys())) + # Keep track of widget indexes + # - we start with 1 because Context item as at the top + widget_idx = 1 + if self._convertors_group is not None: + widget_idx += 1 + + group_by_instance_id = {} + instance_ids_by_group_name = collections.defaultdict(list) + group_icons = { + identifier: self._controller.get_creator_icon(identifier) + for identifier in identifiers + } + for group_name in sorted_group_names: + if group_name not in self._widgets_by_group: + group_widget = BaseGroupWidget( + group_name, self._content_widget + ) + group_widget.double_clicked.connect(self.double_clicked) + self._content_layout.insertWidget(widget_idx, group_widget) + self._widgets_by_group[group_name] = group_widget + + widget_idx += 1 + + instances = instances_by_group[group_name] + for instance in instances: + group_by_instance_id[instance.id] = group_name + instance_ids_by_group_name[group_name].append(instance.id) + + self._update_instances( + group_name, + instances, + context_info_by_id, + parent_active_by_id, + group_icons, + ) + + # Remove empty groups + for group_name in groups_to_remove: widget = self._widgets_by_group.pop(group_name) widget.setVisible(False) self._content_layout.removeWidget(widget) @@ -817,63 +723,85 @@ class InstanceCardView(AbstractInstanceView): if group_name in self._explicitly_selected_groups: self._explicitly_selected_groups.remove(group_name) - # Sort groups - sorted_group_names = list(sorted(instances_by_group.keys())) - - # Keep track of widget indexes - # - we start with 1 because Context item as at the top - widget_idx = 1 - if self._convertor_items_group is not None: - widget_idx += 1 - - for group_name in sorted_group_names: - group_icons = { - identifier: self._controller.get_creator_icon(identifier) - for identifier in identifiers_by_group[group_name] - } - if group_name in self._widgets_by_group: - group_widget = self._widgets_by_group[group_name] - group_widget.update_icons(group_icons) - - else: - group_widget = InstanceGroupWidget( - group_icons, group_name, self._content_widget - ) - group_widget.active_changed.connect(self._on_active_changed) - group_widget.selected.connect(self._on_widget_selection) - group_widget.double_clicked.connect(self.double_clicked) - self._content_layout.insertWidget(widget_idx, group_widget) - self._widgets_by_group[group_name] = group_widget - - widget_idx += 1 - group_widget.update_instances( - instances_by_group[group_name], - context_info_by_id, - parent_active_by_id - ) - group_widget.set_active_toggle_enabled( - self._active_toggle_enabled - ) - - self._update_ordered_group_names() + self._instance_ids_by_parent_id = instance_ids_by_parent_id + self._group_name_by_instance_id = group_by_instance_id + self._instance_ids_by_group_name = instance_ids_by_group_name + self._ordered_groups = sorted_group_names def has_items(self) -> bool: - if self._convertor_items_group is not None: + if self._convertors_group is not None: return True - if self._widgets_by_group: + if self._widgets_by_id: return True return False - def _update_ordered_group_names(self): - ordered_group_names = [CONTEXT_GROUP] - for idx in range(self._content_layout.count()): - if idx > 0: - item = self._content_layout.itemAt(idx) - group_widget = item.widget() - if group_widget is not None: - ordered_group_names.append(group_widget.group_name) + def _update_instances( + self, + group_name: str, + instances: list[InstanceItem], + context_info_by_id: dict[str, InstanceContextInfo], + parent_active_by_id: dict[str, bool], + group_icons: dict[str, str], + ): + """Update instances for the group. - self._ordered_groups = ordered_group_names + Args: + instances (list[InstanceItem]): List of instances in + CreateContext. + context_info_by_id (dict[str, InstanceContextInfo]): Instance + context info by instance id. + parent_active_by_id (dict[str, bool]): Instance has active parent. + + """ + # Store instances by id and by product name + group_widget: BaseGroupWidget = self._widgets_by_group[group_name] + instances_by_id = {} + instances_by_product_name = collections.defaultdict(list) + for instance in instances: + instances_by_id[instance.id] = instance + product_name = instance.product_name + instances_by_product_name[product_name].append(instance) + + to_remove_ids = set( + self._instance_ids_by_group_name[group_name] + ) - set(instances_by_id) + group_widget.take_widgets(to_remove_ids) + + # Sort instances by product name + sorted_product_names = list(sorted(instances_by_product_name.keys())) + + # Add new instances to widget + ordered_ids = [] + widgets_by_id = {} + for product_names in sorted_product_names: + for instance in instances_by_product_name[product_names]: + context_info = context_info_by_id[instance.id] + is_parent_active = parent_active_by_id[instance.id] + if instance.id in self._widgets_by_id: + widget = self._widgets_by_id[instance.id] + widget.update_instance( + instance, context_info, is_parent_active + ) + else: + group_icon = group_icons[instance.creator_identifier] + widget = InstanceCardWidget( + instance, + context_info, + is_parent_active, + group_icon, + group_widget + ) + widget.selected.connect(self._on_widget_selection) + widget.active_changed.connect(self._on_active_changed) + widget.double_clicked.connect(self.double_clicked) + self._widgets_by_id[instance.id] = widget + + ordered_ids.append(instance.id) + widgets_by_id[instance.id] = widget + + group_widget.set_widgets(widgets_by_id, ordered_ids) + + return ordered_ids def _make_sure_context_widget_exists(self): # Create context item if is not already existing @@ -891,28 +819,65 @@ class InstanceCardView(AbstractInstanceView): self.selection_changed.emit() self._content_layout.insertWidget(0, widget) - def _update_convertor_items_group(self): + def _update_convertors_group(self): convertor_items = self._controller.get_convertor_items() - if not convertor_items and self._convertor_items_group is None: + if not convertor_items and self._convertors_group is None: return + ids_to_remove = set(self._convertor_widgets_by_id) - set( + convertor_items + ) + if ids_to_remove: + self._convertors_group.take_widgets(ids_to_remove) + + for conv_id in ids_to_remove: + widget = self._convertor_widgets_by_id.pop(conv_id) + widget.setVisible(False) + widget.deleteLater() + if not convertor_items: - self._convertor_items_group.setVisible(False) - self._content_layout.removeWidget(self._convertor_items_group) - self._convertor_items_group.deleteLater() - self._convertor_items_group = None + self._convertors_group.setVisible(False) + self._content_layout.removeWidget(self._convertors_group) + self._convertors_group.deleteLater() + self._convertors_group = None + self._convertor_ids = [] + self._convertor_widgets_by_id = {} return - if self._convertor_items_group is None: - group_widget = ConvertorItemsGroupWidget( + if self._convertors_group is None: + group_widget = BaseGroupWidget( CONVERTOR_ITEM_GROUP, self._content_widget ) - group_widget.selected.connect(self._on_widget_selection) - group_widget.double_clicked.connect(self.double_clicked) self._content_layout.insertWidget(1, group_widget) - self._convertor_items_group = group_widget + self._convertors_group = group_widget - self._convertor_items_group.update_items(convertor_items) + # TODO create convertor widgets + items_by_label = collections.defaultdict(list) + for item in convertor_items.values(): + items_by_label[item.label].append(item) + + # Sort instances by product name + sorted_labels = list(sorted(items_by_label.keys())) + + # Add new instances to widget + convertor_ids: list[str] = [] + widgets_by_id: dict[str, ConvertorItemCardWidget] = {} + for label in sorted_labels: + for item in items_by_label[label]: + convertor_ids.append(item.id) + if item.id in self._convertor_widgets_by_id: + widget = self._convertor_widgets_by_id[item.id] + widget.update_item(item) + else: + widget = ConvertorItemCardWidget(item, self) + widget.selected.connect(self._on_widget_selection) + widget.double_clicked.connect(self.double_clicked) + self._convertor_widgets_by_id[item.id] = widget + widgets_by_id[item.id] = widget + + self._convertors_group.set_widgets(widgets_by_id, convertor_ids) + self._convertor_ids = convertor_ids + self._convertor_widgets_by_id = widgets_by_id def refresh_instance_states(self, instance_ids=None): """Trigger update of instances on group widgets.""" @@ -922,36 +887,57 @@ class InstanceCardView(AbstractInstanceView): instance_items_by_id = self._controller.get_instance_items_by_id( instance_ids ) - instance_ids = set(instance_items_by_id) + instance_ids: set[str] = set(instance_items_by_id) + available_ids: set[str] = set(instance_items_by_id) + discarted_ids: set[str] = set() - parent_is_active_by_id = { - instance_id: False - for instance_id in instance_ids - } - - discarted_ids = set() _queue = collections.deque() - _queue.append((None, True)) + _queue.append((set(self._instance_ids_by_parent_id[None]), True)) while _queue: - parent_id, parent_is_active = _queue.pop() - for instance_id in self._instance_ids_by_parent_id[parent_id]: + if not instance_ids: + break + + chilren_ids, is_parent_active = _queue.pop() + for instance_id in chilren_ids: + widget = self._widgets_by_id[instance_id] + add_children = False if instance_id in instance_ids: + add_children = ( + is_parent_active is not widget.is_parent_active() + ) + + if instance_id in available_ids: + available_ids.discard(instance_id) + widget.update_instance( + instance_items_by_id[instance_id], + context_info_by_id[instance_id], + is_parent_active, + ) + else: + # TODO implement 'set_parent_active' + widget.set_parent_active(is_parent_active) + instance_ids.discard(instance_id) discarted_ids.add(instance_id) - # TODO there is no way how to get current state - parent_is_active_by_id[instance_id] = parent_is_active - for widget in self._widgets_by_group.values(): - widget.update_instance_values( - context_info_by_id, - instance_items_by_id, - instance_ids, - parent_is_active_by_id, - ) + if not instance_ids: + break - def _on_active_changed(self, group_name, instance_id, value): - group_widget = self._widgets_by_group[group_name] - instance_widget = group_widget.get_widget_by_item_id(instance_id) + if not add_children: + continue + + children_ids = self._instance_ids_by_parent_id[instance_id] + children = { + child_id + for child_id in children_ids + if child_id not in discarted_ids + } + + if children: + _queue.append((children, widget.is_active())) + + def _on_active_changed(self, instance_id, value): + instance_widget = self._widgets_by_id[instance_id] active_state_by_id = {} if not instance_widget.is_selected: active_state_by_id[instance_id] = value @@ -973,10 +959,9 @@ class InstanceCardView(AbstractInstanceView): else: if group_name == CONVERTOR_ITEM_GROUP: - group_widget = self._convertor_items_group + new_widget = self._convertor_widgets_by_id[instance_id] else: - group_widget = self._widgets_by_group[group_name] - new_widget = group_widget.get_widget_by_item_id(instance_id) + new_widget = self._widgets_by_id[instance_id] if selection_type == SelectionTypes.clear: self._select_item_clear(instance_id, group_name, new_widget) @@ -1021,11 +1006,21 @@ class InstanceCardView(AbstractInstanceView): if instance_id == CONTEXT_ID: remove_group = True else: + has_selected_items = False if group_name == CONVERTOR_ITEM_GROUP: - group_widget = self._convertor_items_group + for widget in self._convertor_widgets_by_id.values(): + if widget.is_selected: + has_selected_items = True + break else: - group_widget = self._widgets_by_group[group_name] - if not group_widget.get_selected_widgets(): + group_ids = self._instance_ids_by_group_name[group_name] + for instance_id in group_ids: + widget = self._widgets_by_id[instance_id] + if widget.is_selected: + has_selected_items = True + break + + if not has_selected_items: remove_group = True if remove_group: @@ -1137,10 +1132,16 @@ class InstanceCardView(AbstractInstanceView): sorted_widgets = [self._context_widget] else: if name == CONVERTOR_ITEM_GROUP: - group_widget = self._convertor_items_group + sorted_widgets = [ + self._convertor_widgets_by_id[conv_id] + for conv_id in self._convertor_ids + ] else: - group_widget = self._widgets_by_group[name] - sorted_widgets = group_widget.get_ordered_widgets() + instance_ids = self._instance_ids_by_group_name[name] + sorted_widgets = [ + self._widgets_by_id[instance_id] + for instance_id in instance_ids + ] # Change selection based on explicit selection if start group # was not passed yet @@ -1298,12 +1299,19 @@ class InstanceCardView(AbstractInstanceView): is_convertor_group = group_name == CONVERTOR_ITEM_GROUP if is_convertor_group: - group_widget = self._convertor_items_group + sorted_widgets = [ + self._convertor_widgets_by_id[conv_id] + for conv_id in self._convertor_ids + ] else: - group_widget = self._widgets_by_group[group_name] + instance_ids = self._instance_ids_by_group_name[group_name] + sorted_widgets = [ + self._widgets_by_id[instance_id] + for instance_id in instance_ids + ] group_selected = False - for widget in group_widget.get_ordered_widgets(): + for widget in sorted_widgets: select = False if is_convertor_group: is_in = widget.identifier in s_convertor_identifiers @@ -1325,5 +1333,5 @@ class InstanceCardView(AbstractInstanceView): if self._active_toggle_enabled is enabled: return self._active_toggle_enabled = enabled - for group_widget in self._widgets_by_group.values(): - group_widget.set_active_toggle_enabled(enabled) + for widget in self._widgets_by_id.values(): + widget.set_active_toggle_enabled(enabled)