# -*- coding: utf-8 -*- """ :author: Jeremy Ernst :description: This module contains the class that is a custom QListWidget for displaying components installed in the scene. It has some extras, like buttons next to each item for pinning and aiming the component. """ import os from functools import partial from maya.app.general.mayaMixin import MayaQWidgetBaseMixin import pymel.core as pm from artv2.third_party.Qt import QtWidgets, QtCore, QtGui from artv2.tools.rigging.rig_builder.component_settings_widget import ComponentSettingsWidget import artv2.utilities.component_utilities as component_utils import artv2.utilities.general_utilities as utils import artv2.utilities.interface_utilities as interface_utils import artv2.tools.system.logger.output_logger as logger class InstalledComponentsWidget(MayaQWidgetBaseMixin, QtWidgets.QListWidget): """ This class is a custom QListWidget for displaying installed components in the scene. Each list widget item in the list has three buttons next to it for toggling visibility, pinning and aim mode. :param parent: an instance of the RigBuilderUI that this widget is parented to. .. figure:: /images/installed_components.png :width: 200px :align: center :height: 457px :figclass: align-center """ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def __init__(self, parent=None): super(InstalledComponentsWidget, self).__init__(parent) self.logger = logger.OutputLogger(self.__class__.__name__) self.setMinimumWidth(interface_utils.scale_by_dpi(150)) self.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) self.setSpacing(1) self._parent = parent self.icon_path = utils.return_settings()[2] self.refresh_list() self.setObjectName("mid") self.itemClicked.connect(self._build_component_settings) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def refresh_list(self): """ Refresh the list of installed components. """ self.logger.interface("{0}.refresh_list: Refreshing installed components list.".format(self.__class__.__name__)) self.clear() components = component_utils.get_all_component_names() for component in sorted(components.keys()): self._add_item(component, components.get(component).nodeName()) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _add_item(self, name, item_data): item = QtWidgets.QListWidgetItem() item.setData(QtCore.Qt.UserRole, item_data) widget = QtWidgets.QWidget() layout = QtWidgets.QHBoxLayout(widget) layout.setSpacing(1) layout.setContentsMargins(0, 0, 0, 0) visibility_button = QtWidgets.QPushButton() visibility_button.setMinimumWidth(20) visibility_button.setMaximumWidth(20) visibility_button.setMaximumHeight(20) visibility_button.setCheckable(True) visibility_button.setToolTip("Toggle visibility.") state = self._get_visibility(item) if state: viz_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/visible.png")) else: viz_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/visible_off.png")) visibility_button.setIconSize(QtCore.QSize(18, 18)) visibility_button.setIcon(viz_icon) visibility_button.setChecked(state) visibility_button.clicked.connect(partial(self._set_visibility, item, visibility_button)) layout.addWidget(visibility_button) aim_button = QtWidgets.QPushButton() aim_button.setMinimumWidth(20) aim_button.setMaximumWidth(20) aim_button.setMaximumHeight(20) aim_button.setCheckable(True) aim_button.setToolTip("Toggle aim mode for component.") state = self._get_aim_state(item) if state: aim_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/aim.png")) else: aim_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/aim_off.png")) aim_button.setIconSize(QtCore.QSize(18, 18)) aim_button.setIcon(aim_icon) aim_button.setChecked(state) aim_button.clicked.connect(partial(self._aim_component, item, aim_button)) layout.addWidget(aim_button) pin_button = QtWidgets.QPushButton() pin_button.setMinimumWidth(20) pin_button.setMaximumWidth(20) pin_button.setMaximumHeight(20) pin_button.setCheckable(True) pin_button.setToolTip("Toggle pinning component in place.") state = self._get_pin_state(item) if state: pin_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/pin.png")) else: pin_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/pin_off.png")) pin_button.setIconSize(QtCore.QSize(18, 18)) pin_button.setChecked(state) pin_button.setIcon(pin_icon) pin_button.clicked.connect(partial(self._pin_component, item, pin_button)) layout.addWidget(pin_button) label = QtWidgets.QLabel(name) layout.addWidget(label) # widget.show() item.setSizeHint(widget.sizeHint()) self.addItem(item) self.setItemWidget(item, widget) return item # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _build_component_settings(self, *args): metanode = args[0].data(QtCore.Qt.UserRole) self.logger.interface("{0}._build_component_settings: Building settings widget for {1}".format( self.__class__.__name__, metanode)) interface_utils.clear_layout(self._parent.settings_layout) layout = self.itemWidget(args[0]).layout() for i in range(layout.count()): widget = layout.itemAt(i).widget() if isinstance(widget, QtWidgets.QLabel): ComponentSettingsWidget(metanode, self._parent.settings_layout, args[0], widget, self) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @staticmethod def _get_visibility(item): metanode = item.data(QtCore.Qt.UserRole) inst = component_utils.get_component_instance(pm.PyNode(metanode)) state = inst.network_node.movers_visible.get() del inst return state # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @staticmethod def _get_pin_state(item): metanode = item.data(QtCore.Qt.UserRole) inst = component_utils.get_component_instance(pm.PyNode(metanode)) state = inst.network_node.pinned.get() del inst return state # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @staticmethod def _get_aim_state(item): metanode = item.data(QtCore.Qt.UserRole) inst = component_utils.get_component_instance(pm.PyNode(metanode)) state = inst.network_node.isAiming.get() del inst return state # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _pin_component(self, item, button): metanode = item.data(QtCore.Qt.UserRole) inst = component_utils.get_component_instance(pm.PyNode(metanode)) inst.joint_mover.toggle_pin_component() self.logger.interface("{0}._pin_component: Setting pin mode for {1} to {2}" "".format(self.__class__.__name__, metanode, self._get_pin_state(item))) if self._get_pin_state(item): aim_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/pin.png")) else: aim_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/pin_off.png")) button.setIcon(aim_icon) del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _aim_component(self, item, button): metanode = item.data(QtCore.Qt.UserRole) inst = component_utils.get_component_instance(pm.PyNode(metanode)) inst.joint_mover.aim_helper.toggle_aim_mode() self.logger.interface("{0}._aim_component: Setting aim mode for {1} to {2}" "".format(self.__class__.__name__, metanode, self._get_aim_state(item))) if self._get_aim_state(item): aim_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/aim.png")) else: aim_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/aim_off.png")) button.setIcon(aim_icon) del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def _set_visibility(self, item, button): metanode = item.data(QtCore.Qt.UserRole) inst = component_utils.get_component_instance(pm.PyNode(metanode)) inst.joint_mover.toggle_visibility(button.isChecked()) self.logger.interface("{0}._set_visibility: Setting visibility mode for {1} to {2}" "".format(self.__class__.__name__, metanode, self._get_visibility(item))) if self._get_visibility(item): icon = QtGui.QIcon(os.path.join(self.icon_path, "general/visible.png")) else: icon = QtGui.QIcon(os.path.join(self.icon_path, "general/visible_off.png")) button.setIcon(icon) del inst # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def get_items(self): """ Get the labels of the list widget items and store them in a dictionary where the values are the items. :return: {[label]= QListWidgetItem, } """ items = {} for i in range(self.count()): item = self.item(i) widget = self.itemWidget(item) layout = widget.layout() for index in range(layout.count()): widget = layout.itemAt(index).widget() if isinstance(widget, QtWidgets.QLabel): text = widget.text() items[text] = item return items # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # def filter_list(self, search_widget): """ Filters the list widget by the search term in the given search widget. :param search_widget: QLineEdit widget to grab text from for search term. """ search_term = search_widget.text() items = self.get_items() for item in items: widget_item = items.get(item) if search_term in item: widget_item.setHidden(False) else: widget_item.setHidden(True)