def open_window(cls, show=True, auto_raise=True, delete=False, dock=False): s = time.time() if (cls is not None and uiutils.isValidQtObject(cls.instance) is True): if delete is True: cls.instance.close() cls.instance.deleteLater() if (cls.instance is None or uiutils.isValidQtObject(cls.instance) is False): name = cls.name app, parent = uiutils.getParent() cls.instance = cls(parent=parent, name=name) cls.instance.setDockableParameters(dockable=dock) # Make sure the user can see this window. if cls.instance.isHidden(): if show is True: cls.instance.show() if auto_raise is True: # Force the window state to bring the window to the # front, and "restore" the state, even if the window # is minimised. Confirmed to work on MS Windows 10. state = cls.instance.windowState() state = QtCore.Qt.WindowNoState state |= QtCore.Qt.WindowActive cls.instance.setWindowState(state) cls.instance.raise_() cls.instance.show() cls.instance.activateWindow() e = time.time() LOG.debug('BaseWindow init: %r seconds', e - s) return cls.instance
def setSolveInfoLine(self, text): valid = uiutils.isValidQtObject(self) if valid is False: return valid = uiutils.isValidQtObject(self.solver_state) if valid is False: return self.solver_state.setSolveInfoLine(text) return
def setSolveInfoLine(self, text): valid = uiutils.isValidQtObject(self) if valid is False: return valid = uiutils.isValidQtObject(self.solveInfoLine_lineEdit) if valid is False: return self.solveInfoLine_lineEdit.setText(text) return
def setStatusLine(self, text): valid = uiutils.isValidQtObject(self) if valid is False: return valid = uiutils.isValidQtObject(self.statusLine_label) if valid is False: return self.statusLine_label.setText(text) return
def setNodeSelectionWithUUID(tree_view, model, filter_model, sel_model, column_name, values): """ Override the tree view selection based on Maya Node UUIDs. """ # Ensure we don't try to access the Qt objects if they no longer # exist in memory. objs = [tree_view, model, filter_model, sel_model] for obj in objs: valid = uiutils.isValidQtObject(obj) if valid is False: return root_index = tree_view.rootIndex() column = model.getColumnIndexFromColumnName(column_name) indexes = _lookupIndexesFromMayaNodeUUIDs( values, root_index, column, model, ) sel_model.clearSelection() # replace the selection. flags = QtCore.QItemSelectionModel.Select flags |= QtCore.QItemSelectionModel.Rows for index in indexes: new_index = filter_model.mapFromSource(index) sel_model.select(new_index, flags) return
def populateModel(self, model, col): s = time.time() valid = uiutils.isValidQtObject(model) if valid is False: return attr_list = [] show_anm = const.ATTRIBUTE_TOGGLE_ANIMATED_DEFAULT_VALUE show_stc = const.ATTRIBUTE_TOGGLE_STATIC_DEFAULT_VALUE show_lck = const.ATTRIBUTE_TOGGLE_LOCKED_DEFAULT_VALUE if col is not None: attr_list = lib_attr.get_attributes_from_collection(col) show_anm = lib_col.get_attribute_toggle_animated_from_collection( col) show_stc = lib_col.get_attribute_toggle_static_from_collection(col) show_lck = lib_col.get_attribute_toggle_locked_from_collection(col) # Add Callbacks # # When querying attributes, we must make sure they have a Maya # callback attached to the node to update the UI. callback_manager = self.callback_manager if callback_manager is not None: lib_attr.add_callbacks_to_attributes( attr_list, callback_manager, ) root = convert_to_ui.attributesToUINodes(col, attr_list, show_anm, show_stc, show_lck) model.setRootNode(root) e = time.time() LOG.debug('populateModel: %r', e - s) return
def populateModel(self, model): valid = uiutils.isValidQtObject(model) if valid is False: return col = lib_state.get_active_collection() attr_list = [] show_anm = const.ATTRIBUTE_TOGGLE_ANIMATED_DEFAULT_VALUE show_stc = const.ATTRIBUTE_TOGGLE_STATIC_DEFAULT_VALUE show_lck = const.ATTRIBUTE_TOGGLE_LOCKED_DEFAULT_VALUE if col is not None: attr_list = lib_attr.get_attributes_from_collection(col) show_anm = lib_col.get_attribute_toggle_animated_from_collection( col) show_stc = lib_col.get_attribute_toggle_static_from_collection(col) show_lck = lib_col.get_attribute_toggle_locked_from_collection(col) def update_func(): if uiutils.isValidQtObject(self) is False: return self.dataChanged.emit() return # Add Callbacks # # When querying attributes, we must make sure they have a Maya # callback attached to the node to update the UI. callback_manager = self.callback_manager if callback_manager is not None: lib_attr.add_callbacks_to_attributes(attr_list, update_func, callback_manager) root = convert_to_ui.attributesToUINodes(col, attr_list, show_anm, show_stc, show_lck) model.setRootNode(root) return
def main(show=True, widthHeight=(800, 600)): # Force the Plug-in to load. If the plug-in cannot load, the UI # will not open and an error will be given. lib_maya_utils.ensure_plugin_loaded() global UI valid = uiutils.isValidQtObject(UI) if UI is not None and valid is True: UI.close() name = 'SolverWindow' app, parent = uiutils.getParent() UI = SolverWindow(parent=parent, name=name) if not UI: return UI if show: UI.show() if ((isinstance(widthHeight, (tuple, list)) is True) and (len(widthHeight) == 2)): pos = UI.pos() UI.setGeometry(pos.x(), pos.y(), widthHeight[0], widthHeight[1]) # Enter Qt application main loop if app is not None: sys.exit(app.exec_()) return UI
def populateAttributeModel(self, model): valid = uiutils.isValidQtObject(model) if valid is False: return col = lib_state.get_active_collection() attr_list = [] if col is not None: attr_list = lib_attr.get_attributes_from_collection(col) def update_func(): if uiutils.isValidQtObject(self) is False: return self.updateAttributeModel() return # Add Callbacks # # When querying attributes, we must make sure they have a Maya # callback attached to the node to update the UI. callback_manager = self.getCallbackManager() if callback_manager is not None: lib_attr.add_callbacks_to_attributes( attr_list, update_func, callback_manager ) root = convert_to_ui.attributesToUINodes(attr_list) model.setRootNode(root) return
def run_solve(override_current_frame=None): """ Run the solver for the active collection. If the Solver UI is found, the window will update and show progress messages. This function is strongly dependant on the Solver UI. The following state information is set via the Solver UI. - Active Collection - Log Level - Refresh Viewport :param override_current_frame: Before running the solver, change the "override current frame" state to this value. :type override_current_frame: bool """ assert (override_current_frame is None or isinstance(override_current_frame, bool)) if override_current_frame is None: override_current_frame = False col = lib_state.get_active_collection() if col is None: msg = 'No active Collection found. Skipping solve.' LOG.warning(msg) return log_level = lib_state.get_log_level() layout = None win = solver_window.SolverWindow.get_instance() win_valid = uiutils.isValidQtObject(win) if win is None and win_valid: msg = 'Could not get window.' LOG.warning(msg) else: layout = win.getSubForm() # Set 'override current frame' value. tab = lib_col_state.get_solver_tab_from_collection(col) prev_value = None if override_current_frame is True: prev_value = __get_override_current_frame_value(col, tab) __set_override_current_frame_value(col, layout, tab, override_current_frame) # Run Solver options = lib_col.gather_execute_options() lib_col.run_solve_ui( col, options, log_level, win, ) # Restore previous value. if override_current_frame is True: __set_override_current_frame_value(col, layout, tab, prev_value) return
def main(show=True, widthHeight=(400, 100)): global MM_SOLVER_CHAN_SENSE_UI valid = uiutils.isValidQtObject(MM_SOLVER_CHAN_SENSE_UI) if MM_SOLVER_CHAN_SENSE_UI is not None and valid is True: MM_SOLVER_CHAN_SENSE_UI.close() name = 'ChannelSenWindow' app, parent = uiutils.getParent() MM_SOLVER_CHAN_SENSE_UI = ChannelSenWindow(parent=parent, name=name) if not MM_SOLVER_CHAN_SENSE_UI: return MM_SOLVER_CHAN_SENSE_UI if show: MM_SOLVER_CHAN_SENSE_UI.show() if ((isinstance(widthHeight, (tuple, list)) is True) and (len(widthHeight) == 2)): pos = MM_SOLVER_CHAN_SENSE_UI.pos() MM_SOLVER_CHAN_SENSE_UI.setGeometry(pos.x(), pos.y(), widthHeight[0], widthHeight[1]) # Enter Qt application main loop if app is not None: sys.exit(app.exec_()) return MM_SOLVER_CHAN_SENSE_UI
def update_func(): if uiutils.isValidQtObject(self) is False: return self.updateObjectToggleButtons() self.updateObjectModel() self.updateSolveValidState() return
def update_func(): if uiutils.isValidQtObject(self) is False: return self.updateAttributeToggleButtons() self.updateAttributeColumnVisibility() self.updateAttributeModel() self.updateSolveValidState() return
def __set_window_instance(window): """ Set the stored instance of the Solver window. """ global MM_SOLVER_SOLVER_UI valid = uiutils.isValidQtObject(MM_SOLVER_SOLVER_UI) if valid is True: MM_SOLVER_SOLVER_UI = window return
def updateAttributeModel(self): self.populateAttributeModel(self.attribute_model) valid = uiutils.isValidQtObject(self.attribute_treeView) if valid is False: return self.attribute_treeView.expandAll() widgets = [self.attribute_frame] self.populateWidgetsEnabled(widgets) return
def populateModel(self, model): """ Set the model based on the current Maya scene state. """ valid = uiutils.isValidQtObject(model) if valid is False: return string_data_list = self.getRangeTypeStringDataList() model.setStringDataList(string_data_list) return
def populateCollectionModel(self, model): valid = uiutils.isValidQtObject(model) if valid is False: return cols = lib_col.get_collections() string_data_list = [] for col in cols: node = col.get_node() string_data_list.append((node, col)) model.setStringDataList(string_data_list) return
def populateSolverModel(self, model): valid = uiutils.isValidQtObject(model) if valid is False: return col = lib_state.get_active_collection() if col is None: step_list = [] else: step_list = lib_col.get_solver_steps_from_collection(col) node_list = convert_to_ui.solverStepsToUINodes(step_list, col) self.solver_model.setNodeList(node_list) return
def get_window_instance(): """ Get the currently running instance of the Solver window. :returns: An object of SolverWindow, or None. :rtype: SolverWindow or None """ global MM_SOLVER_SOLVER_UI valid = uiutils.isValidQtObject(MM_SOLVER_SOLVER_UI) if MM_SOLVER_SOLVER_UI is None or valid is False: return None return MM_SOLVER_SOLVER_UI
def apply(self): """ This button launches a solve, but can also be used to cancel a solve. """ running_state = lib_state.get_solver_is_running_state() if running_state is True: # Cancel out of a running solve if the user presses # the button again. lib_state.set_solver_user_interrupt_state(True) return if uiutils.isValidQtObject(self) is False: return undo_id = 'mmSolver: ' undo_id += str(datetime.datetime.isoformat(datetime.datetime.now())) undo_id += ' ' undo_id += str(uuid.uuid4()) with tools_utils.tool_context(use_undo_chunk=True, undo_chunk_name=undo_id, restore_current_frame=False, pre_update_frame=False, post_update_frame=False, use_dg_evaluation_mode=True, disable_viewport=False): block = self.blockSignals(True) try: mmapi.set_solver_running(True) self.applyBtn.setText(const.WINDOW_BUTTON_SOLVE_STOP_LABEL) self.closeBtn.setText(const.WINDOW_BUTTON_CLOSE_AND_STOP_LABEL) options = lib_collection.gather_execute_options() log_level = lib_state.get_log_level() col = lib_state.get_active_collection() lib_collection.run_solve_ui(col, options, log_level, self) finally: mmapi.set_solver_running(False) if uiutils.isValidQtObject(self) is True: self.applyBtn.setText( const.WINDOW_BUTTON_SOLVE_START_LABEL) self.closeBtn.setText(const.WINDOW_BUTTON_CLOSE_LABEL) self.blockSignals(block) return
def close_all_instances(cls): global ALL_CLASS_INSTANCES for instance in ALL_CLASS_INSTANCES: if not instance: continue if uiutils.isValidQtObject(instance) is False: continue LOG.debug("Closing: %r", instance.objectName()) instance.deleteLater() instance.close() del ALL_CLASS_INSTANCES ALL_CLASS_INSTANCES = set() return
def open_window(cls, show=True, auto_raise=True, delete=False): if (cls is not None and uiutils.isValidQtObject(cls.instance) is False): if delete is True: cls.instance.close() cls.instance.deleteLater() if (cls.instance is None or uiutils.isValidQtObject(cls.instance) is False): name = cls.name app, parent = uiutils.getParent() cls.instance = cls(parent=parent, name=name) # Make sure the user can see this window. if cls.instance.isHidden(): if show is True: cls.instance.show() else: if auto_raise is True: cls.instance.raise_() cls.instance.activateWindow() return cls.instance
def populateModel(self, model): """ Set the model based on the current Maya scene state. """ valid = uiutils.isValidQtObject(model) if valid is False: return cols = lib_col.get_collections() string_data_list = [] for col in cols: node = col.get_node() string_data_list.append((node, col)) model.setStringDataList(string_data_list) return
def setMinimalUI(self, value): """ Change the currently open Solver window to be "minimal", or not. If the Solver window is not open, nothing happens. "minimal" UI means hiding most widgets in the Solver UI, and not "minimal" means showing all widgets as a user normally would expect. """ assert isinstance(value, bool) def _set_widget_visibilty(window, visible): self.menubar.setVisible(visible) self.subForm.collection_widget.setVisible(visible) self.subForm.object_browser.setVisible(visible) self.subForm.attribute_browser.setVisible(visible) self.subForm.solver_settings.setVisible(visible) self.subForm.ui.objectAttribute_splitter.setVisible(visible) self.subForm.ui.line_1.setVisible(visible) self.subForm.ui.line_2.setVisible(visible) if uiutils.isValidQtObject(self) is True: QtWidgets.QApplication.processEvents() if value is False: _set_widget_visibilty(self, True) # Restore non-minimal window size. QtWidgets.QApplication.processEvents() self.resize(self._saved_ui_size) else: self._saved_ui_size = self.size() # QtWidgets.QApplication.processEvents() _set_widget_visibilty(self, False) QtWidgets.QApplication.processEvents() # Resize the bottom window edge upwards. width = self.size().width() self.resize(width, 1) QtWidgets.QApplication.processEvents() # Run again to trigger the UI to resize properly. _set_widget_visibilty(self, False) self.resize(width, 1) QtWidgets.QApplication.processEvents() QtWidgets.QApplication.processEvents() return
def populateModel(self, model, col): valid = uiutils.isValidQtObject(model) if valid is False: return mkr_list = [] show_cam = const.OBJECT_TOGGLE_CAMERA_DEFAULT_VALUE show_mkr = const.OBJECT_TOGGLE_MARKER_DEFAULT_VALUE show_bnd = const.OBJECT_TOGGLE_BUNDLE_DEFAULT_VALUE if col is not None: mkr_list = lib_marker.get_markers_from_collection(col) show_cam = lib_col.get_object_toggle_camera_from_collection(col) show_mkr = lib_col.get_object_toggle_marker_from_collection(col) show_bnd = lib_col.get_object_toggle_bundle_from_collection(col) root = convert_to_ui.markersToUINodes(mkr_list, show_cam, show_mkr, show_bnd) model.setRootNode(root) return
def selection_changed_func(clientData): """The Maya selection has changed, we must synchronize the Maya selection with the Solver UI. :param clientData: The Qt window object class. :type clientData: SolverWindow :return: Nothing. :rtype: None """ if mmapi.is_solver_running() is True: return sel_uuids = maya.cmds.ls(selection=True, uuid=True) or [] valid = uiutils.isValidQtObject(clientData) if clientData is not None and valid is True: clientData.setNodeSelection(sel_uuids) return
def updateModel(self): is_running = mmapi.is_solver_running() if is_running is True: return self.populateModel(self.model) valid = uiutils.isValidQtObject(self.treeView) if valid is False: return self.treeView.expandAll() widgets = [self] _populateWidgetsEnabled(widgets) block = self.blockSignals(True) self.dataChanged.emit() self.blockSignals(block) return
def getDefaultCollectionIndex(self, model, col): """ Get the index for the 'currently selected' collection. """ valid = uiutils.isValidQtObject(model) if valid is False: return if col is None: return None active_node = col.get_node() if active_node is None: return None string_data_list = model.stringDataList() string_list = [string for string, data in string_data_list] index = None if active_node in string_list: index = string_list.index(active_node) return index
def getRangeTypeActiveIndex(self, model, col): """ Get the index for the 'currently selected' frame range type. """ valid = uiutils.isValidQtObject(model) if valid is False: return if col is None: return None active_node = col.get_node() if active_node is None: return None value = self.getRangeTypeValue(col) string_data_list = model.stringDataList() data_list = [data for string, data in string_data_list] index = None if value in data_list: index = data_list.index(value) return index
def new_scene_func(clientData): """ Create a callback called just before a new scene file is created or before a new file is loaded. The UI must be closed. All data structures stored must be removed. :param clientData: The Qt window object class. :type clientData: SolverWindow :return: Nothing. :rtype: None """ try: valid = uiutils.isValidQtObject(clientData) if clientData is not None and valid is True: clientData.close() except RuntimeError: msg = 'New Maya Scene callback failed to close UI: ui=%r' LOG.warning(msg, clientData) return