def close_tool(self, tool_id, force=True): """ Closes tool with given ID :param tool_id: str """ if tool_id not in self._loaded_tools: return False closed_tool = False parent = dcc.get_main_window() if parent: for child in parent.children(): if child.objectName() == tool_id: child.fade_close() if hasattr( child, 'fade_close') else child.close() closed_tool = True tool_to_close = self._loaded_tools[tool_id].attacher try: if not closed_tool and tool_to_close: tool_to_close.fade_close() if hasattr( tool_to_close, 'fade_close') else tool_to_close.close() if force and tool_to_close: tool_to_close.setParent(None) tool_to_close.deleteLater() except RuntimeError: pass self._loaded_tools.pop(tool_id) return True
def __init__(self, name='SaveFile', title='Save File', size=(200, 125), fixed_size=False, frame_less=True, hide_title=False, parent=None, use_app_browser=False): parent = parent or dcc.get_main_window() super(BaseSaveFileDialog, self).__init__(name=name, title=title, size=size, fixed_size=fixed_size, frame_less=frame_less, hide_title=hide_title, use_app_browser=use_app_browser, parent=parent) self._open_button.setText('Save') size = QSize(42, 24) self.new_directory_button = QPushButton('New') self.new_directory_button.setToolTip('Create new directory') self.new_directory_button.setMinimumSize(size) self.new_directory_button.setMaximumWidth(size) self.new_directory_button.clicked.connect(self.create_new_directory) self.grid.itemAtPosition(0, 1).addWidget(self.new_directory_button, 0, 5)
def __init__(self, name='OpenFile', multi=False, title='Open File', size=(200, 125), fixed_size=False, frame_less=True, hide_title=False, parent=None, use_app_browser=False): parent = parent or dcc.get_main_window() super(BaseOpenFileDialog, self).__init__(name=name, title=title, size=size, fixed_size=fixed_size, frame_less=frame_less, hide_title=hide_title, use_app_browser=use_app_browser, parent=parent) self._multi = multi if multi: self.setExtendedSelection()
def warning(message): """ Prints a warning message :param message: str :return: """ QMessageBox.warning(dcc.get_main_window(), 'Warning', message)
def __init__(self, name='MayaColorDialog', parent=None, **kwargs): parent = parent or dcc.get_main_window() super(BaseColorDialog, self).__init__(name=name, parent=parent, **kwargs) self._color = None
def show_at(self, pos, content, parent_window=None): """ Shows tooltip in given position and with given widget :param pos: QPoint :param content: QWidget :param parent_window: QWindow """ parent_window = parent_window or dcc.get_main_window().windowHandle() self._add_widget(content) self._show(pos, parent_window)
def _show_bones_hierarchy(self, file_path): dlg = QDialog(parent=dcc.get_main_window() or None) dlg.setWindowTitle('Select Skeleton Node') lyt = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0)) dlg.setLayout(lyt) bone_hierarchy_widget = BoneHierarchyWidget(file_path, parent=dlg) current_bone = self.text() or '' bone_hierarchy_widget.set_bone(current_bone) lyt.addWidget(bone_hierarchy_widget) dlg.exec_() selected_node = bone_hierarchy_widget.selected_node if not selected_node: return self.setText(selected_node)
def _update_position(self): """ Internal function that makes sure that panel is positioned in the proper place """ parent = self.parent() parent_parent = parent.parent() dcc_win = dcc.get_main_window() dcc_window = parent_parent == dcc_win if parent_parent and dcc_win: dcc_window = dcc_window or parent_parent.objectName( ) == dcc_win.objectName() parent_geo = parent.geometry() if self._position == SliderPanelPositions.LEFT: pos = parent_geo.topLeft() if dcc_window else parent.mapToGlobal( parent_geo.topLeft()) target_x = pos.x() target_y = pos.y() self.setFixedHeight(parent_geo.height()) self._pos_anim.setStartValue( QPoint(target_x - self.width(), target_y)) self._pos_anim.setEndValue(QPoint(target_x, target_y)) if self._position == SliderPanelPositions.RIGHT: pos = parent_geo.topRight() if dcc_window else parent.mapToGlobal( parent_geo.topRight()) self.setFixedHeight(parent_geo.height()) target_x = pos.x() - self.width() target_y = pos.y() self._pos_anim.setStartValue( QPoint(target_x + self.width(), target_y)) self._pos_anim.setEndValue(QPoint(target_x, target_y)) if self._position == SliderPanelPositions.TOP: pos = parent_geo.topLeft( ) if dcc_window or parent_parent is None else parent.mapToGlobal( parent_geo.topLeft()) self.setFixedWidth(parent_geo.width()) target_x = pos.x() target_y = pos.y() self._pos_anim.setStartValue( QPoint(target_x, target_y - self.height())) self._pos_anim.setEndValue(QPoint(target_x, target_y)) if self._position == SliderPanelPositions.BOTTOM: pos = parent_geo.bottomLeft( ) if dcc_window else parent.mapToGlobal(parent_geo.bottomLeft()) self.setFixedWidth(parent_geo.width()) target_x = pos.x() target_y = pos.y() - self.height() self._pos_anim.setStartValue( QPoint(target_x, target_y + self.height())) self._pos_anim.setEndValue(QPoint(target_x, target_y))
def __init__(self, **kwargs): parent = kwargs.get('parent', None) or dcc.get_main_window() super(BaseDialog, self).__init__(parent=parent) self._setup_resizers() title = kwargs.get('title', '') name = kwargs.get('name', title or self.__class__.__name__) width = kwargs.get('width', 600) height = kwargs.get('height', 800) show_on_initialize = kwargs.get('show_on_initialize', False) self._theme = None self._dpi = kwargs.get('dpi', 1.0) self._fixed_size = kwargs.get('fixed_size', False) self._has_title = kwargs.pop('has_title', False) self._size = kwargs.pop('size', (200, 125)) self._title_pixmap = kwargs.pop('title_pixmap', None) self._toolset = kwargs.get('toolset', None) self.setObjectName(str(name)) self.setFocusPolicy(Qt.StrongFocus) frameless = kwargs.get('frameless', True) self.set_frameless(frameless) self.ui() self.setup_signals() self._status_bar = QStatusBar(self) self.main_layout.addWidget(self._status_bar) if self._fixed_size: self._status_bar.hide() self._status_bar.hide() self.setWindowTitle(title) auto_load = kwargs.get('auto_load', True) if auto_load: self.load_theme() if show_on_initialize: self.center() self.show() if self._toolset: self.main_layout.addWidget(self._toolset) self.resize(width, height)
def show_below(self, rect, content, parent_window=None): """ Shows tooltip below given rect and with given content :param rect: QRect :param content: QWidget :param parent_window: QWindow """ parent_window = parent_window or dcc.get_main_window().windowHandle() self._add_widget(content) margin_size = QSize( 2 * content.style().pixelMetric(QStyle.PM_DefaultTopLevelMargin), 2 * content.style().pixelMetric(QStyle.PM_DefaultTopLevelMargin) ) content.setMaximumSize(parent_window.screen().geometry().size() - margin_size) self._show(self._center_below(rect, parent_window.screen()), parent_window)
def get_window_menu_bar(window=None): """ Returns menu bar of given window. If not given, DCC main window will be used :param window: QMainWindow :return: QMenuBar or None """ window = window or dcc.get_main_window() if not window: return if hasattr(window, 'menuBar'): return window.menuBar() else: menu_bars = window.findChildren(QMenuBar) if not menu_bars: return None return menu_bars[0]
def _get_center_position(self, parent): parent_parent = parent.parent() dcc_win = dcc.get_main_window() if dcc_win: dcc_window = parent_parent == dcc_win or parent_parent.objectName( ) == dcc_win.objectName() else: dcc_window = None parent_geo = parent.geometry() pos = parent_geo.topLeft() if dcc_window else parent.mapToGlobal( parent_geo.topLeft()) offset = 0 for child in parent.children(): if isinstance(child, BaseToast) and child.isVisible(): offset = max(offset, child.y()) target_x = pos.x() + parent_geo.width() / 2 - self.width() / 2 target_y = pos.y() + parent_geo.height() / 2 - self.height() / 2 self.setProperty('pos', QPoint(target_x, target_y))
def confirm_dialog(title, message, button=None, cancel_button=None, default_button=None, dismiss_string=None): """ Shows DCC confirm dialog :param title: :param message: :param button: :param cancel_button: :param default_button: :param dismiss_string: :return: """ return QMessageBox.question(dcc.get_main_window(), title, message)
def create_main_menu(package_name, force_creation=True, icon=None): """ Creates main menu for given package :param package_name: str :param force_creation: bool :param icon: QIcon """ if not package_name: return None object_menu_name = _OBJECT_MENU_NAMES[ package_name] if package_name in _OBJECT_MENU_NAMES else '{}_Menu'.format( package_name) if package_name in _MENUS and _MENUS.get( package_name, None) and object_menu_name in _MENUS[package_name]: if not force_creation: return _MENUS[package_name][object_menu_name] remove_previous_menus(package_name=package_name) menu_name = _MENU_NAMES[ package_name] if package_name in _MENU_NAMES else package_name main_win = dcc.get_main_window() parent_menu_bar = main_win.menuBar() if main_win else None if not parent_menu_bar: logger.warning( 'Impossible to create Tools main menu for "{}" because not found menu bar to attach menu to!' .format(package_name)) return None main_menu = menu.SearchableMenu(objectName=object_menu_name, title=menu_name, parent=parent_menu_bar) if icon: main_menu.setIcon(icon) parent_menu_bar.addMenu(main_menu) main_menu.setObjectName(object_menu_name) main_menu.setTearOffEnabled(True) _MENU_NAMES.setdefault(package_name, list()) _MENUS.setdefault(package_name, dict()) _MENUS[package_name].setdefault(object_menu_name, main_menu) _MENU_NAMES[package_name].append(object_menu_name) return main_menu
def _set_proper_position(self, parent): parent_parent = parent.parent() dcc_win = dcc.get_main_window() if dcc_win: dcc_window = parent_parent == dcc_win or parent_parent.objectName( ) == dcc_win.objectName() else: dcc_window = None parent_geo = parent.geometry() pos = parent_geo.topLeft() if dcc_window else parent.mapToGlobal( parent_geo.topLeft()) # pos = parent_geo.topLeft() if parent.parent() is None else parent.mapToGlobal(parent_geo.topLeft()) offset = 0 for child in parent.children(): if isinstance(child, PopupMessage) and child.isVisible(): offset = max(offset, child.y()) base_pos = pos.y() + PopupMessage.DEFAULT_CONFIG.get('top') target_x = pos.x() + parent_geo.width() / 2 - 100 target_y = (offset + 50) if offset else base_pos self._pos_anim.setStartValue(QPoint(target_x, target_y - 40)) self._pos_anim.setEndValue(QPoint(target_x, target_y))
def close_tool(self, tool_id, package_name=None, force=True): """ Closes tool with given ID :param tool_id: str :param package_name: str :param force: bool """ tool_class = self.get_plugin_from_id(tool_id, package_name=package_name) if not tool_class or package_name not in self._loaded_tools or tool_id not in self._loaded_tools[ package_name]: return False closed_tool = False # NOTE: Here we do not use a client because this is only valid if the tools is being executed inside DCC parent = dcc.get_main_window() if parent: for child in parent.children(): if child.objectName() == tool_id: child.fade_close() if hasattr( child, 'fade_close') else child.close() closed_tool = True tool_to_close = self._loaded_tools[package_name][tool_id].attacher try: if not closed_tool and tool_to_close: tool_to_close.fade_close() if hasattr( tool_to_close, 'fade_close') else tool_to_close.close() if force and tool_to_close: tool_to_close.setParent(None) tool_to_close.deleteLater() except RuntimeError: pass self._loaded_tools[package_name].pop(tool_id) if not self._loaded_tools[package_name]: self._loaded_tools.pop(package_name) return True
def remove_previous_menus(package_name=None, parent=None): """ Removes any DCC tool menu from DCC by iterating through the children of the main window looking for any widget with proper objectName """ LOGGER.info('Closing menus for: {}'.format(package_name)) deleted_menus = list() parent = parent or dcc.get_main_window() if not parent: return object_menu_name = _OBJECT_MENU_NAMES[ package_name] if package_name in _OBJECT_MENU_NAMES else '{}_Menu'.format( package_name) if not parent: return for child_widget in parent.menuBar().children(): child_name = child_widget.objectName() for pkg_name, menus_data in _MENUS.items(): if package_name and pkg_name != package_name: continue for menu_name, menu_wigdet in menus_data.items(): if child_name == menu_wigdet.objectName(): child_action = child_widget.menuAction() parent.menuBar().removeAction(child_action) child_action.deleteLater() child_widget.deleteLater() _MENUS.pop(package_name) deleted_menus.append(child_name) if child_name == object_menu_name and child_name not in deleted_menus: child_action = child_widget.menuAction() parent.menuBar().removeAction(child_action) child_action.deleteLater() child_widget.deleteLater()
def __init__(self, name='SelectFolder', title='Select Folder', size=(200, 125), fixed_size=False, frame_less=True, hide_title=False, use_app_browser=False, parent=None, **kwargs): parent = parent or dcc.get_main_window() super(BaseSelectFolderDialog, self).__init__(name=name, title=title, size=size, fixed_size=fixed_size, frame_less=frame_less, hide_title=hide_title, use_app_browser=use_app_browser, parent=parent, **kwargs)
def invoke_dock_plugin_by_name(package_name, plugin_name, parent_window=None, settings=None, **kwargs): plugin_class = None parent_window = parent_window or dcc.get_main_window() if package_name not in _PLUGIN_CLASSES: logger.warning('Plugin Package with name "{}" not registered'.format(package_name)) return None for t in _PLUGIN_CLASSES[package_name]: if t.NAME == plugin_name: plugin_class = t break if not plugin_class: logger.warning('No registered tool found with name: "{}"'.format(plugin_name)) return None _PLUGINS.setdefault(package_name, set()) tool_instance = plugin.create_plugin_instance(plugin_class, _PLUGINS[package_name], **kwargs) if not tool_instance: return None if plugin_class.NAME in [t.NAME for t in _PLUGINS[package_name]] and plugin_class.IS_SINGLETON: return tool_instance register_plugin_instance(package_name, tool_instance) if settings: tool_instance.restore_state(settings) # if not restoreDockWidget(tool_instance): # pass else: parent_window.addDockWidget(tool_instance.DEFAULT_DOCK_AREA, tool_instance) tool_instance.app = parent_window tool_instance.show_plugin() return tool_instance
def create_main_menu(package_name, force_creation=True): """ Creates main menu for given package :param package_name: str :param force_creation: bool """ if not package_name: return None if package_name in _MENUS and _MENUS.get(package_name, None): if not force_creation: return _MENUS[package_name] remove_previous_menus(package_name=package_name) object_menu_name = _OBJECT_MENU_NAMES[ package_name] if package_name in _OBJECT_MENU_NAMES else '{}_Menu'.format( package_name) menu_name = _MENU_NAMES[ package_name] if package_name in _MENU_NAMES else package_name main_win = dcc.get_main_window() parent_menu_bar = main_win.menuBar() if main_win else None if not parent_menu_bar: LOGGER.warning( 'Impossible to create Tools main menu for "{}" because not found menu bar to attach menu to!' .format(package_name)) return None main_menu = menu.SearchableMenu(objectName=object_menu_name, title=menu_name, parent=parent_menu_bar) parent_menu_bar.addMenu(main_menu) main_menu.setObjectName(object_menu_name) main_menu.setTearOffEnabled(True) return main_menu
def __init__(self, name='messageBox', width=None, height=None, enable_input_edit=False, enable_dont_show_checkbox=False, parent=None): super(MessageBox, self).__init__(parent=parent) self._frame = None self._animation = None self._dont_show_checkbox = False self._clicked_button = None self._clicked_standard_button = None self.setMinimumWidth(width or self.MAX_WIDTH) self.setMinimumHeight(height or self.MAX_HEIGHT) self.setObjectName(name) self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint) self.setAttribute(Qt.WA_TranslucentBackground) # self.setStyleSheet('background-color: rgb(68, 68, 68, 255);') parent = self.parent() self._frame = None if parent and parent != dcc.get_main_window(): parent.installEventFilter(self) self._frame = QFrame(parent) self._frame.setStyleSheet( 'background-color: rgba(25, 25, 25, 150);') self._frame.setObjectName('messageBoxFrame') self._frame.show() self.setParent(self._frame) self.main_layout = layouts.VerticalLayout(spacing=0, margins=(0, 0, 0, 0)) self.setLayout(self.main_layout) self._header = QFrame(self) self._header.setFixedHeight(46) self._header.setObjectName('messageBoxHeaderFrame') self._header.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self._icon = label.BaseLabel(parent=self._header) self._icon.hide() self._icon.setFixedHeight(32) self._icon.setFixedHeight(32) self._icon.setScaledContents(True) self._icon.setAlignment(Qt.AlignTop) self._icon.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self._title = label.BaseLabel(parent=self._header) self._title.setObjectName('messageBoxHeaderLabel') self._title.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) hlayout = layouts.HorizontalLayout(spacing=10, margins=(15, 7, 15, 10)) hlayout.addWidget(self._icon) hlayout.addWidget(self._title) self._header.setLayout(hlayout) body_layout = layouts.VerticalLayout() self._body = QFrame(self) self._body.setObjectName('messageBoxBody') self._body.setLayout(body_layout) self._message = label.BaseLabel(parent=self._body) self._message.setWordWrap(True) self._message.setMinimumHeight(15) self._message.setAlignment(Qt.AlignLeft) self._message.setTextInteractionFlags(Qt.TextSelectableByMouse) self._message.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) body_layout.addWidget(self._message) body_layout.setContentsMargins(15, 15, 15, 15) if enable_input_edit: self._input_edit = lineedit.BaseLineEdit(parent=self._body) self._input_edit.setObjectName('messageBoxInputEdit') self._input_edit.setMinimumHeight(32) self._input_edit.setFocus() body_layout.addStretch(1) body_layout.addWidget(self._input_edit) body_layout.addStretch(10) if enable_dont_show_checkbox: msg = 'Do not show this message again' self._dont_show_checkbox = checkbox.BaseCheckBox(msg, parent=self._body) body_layout.addStretch(10) body_layout.addWidget(self._dont_show_checkbox) body_layout.addStretch(2) self._button_box = QDialogButtonBox(None, Qt.Horizontal, self) self._button_box.clicked.connect(self._on_clicked) self._button_box.accepted.connect(self._on_accept) self._button_box.rejected.connect(self._on_reject) self.main_layout.addWidget(self._header) self.main_layout.addWidget(self._body) body_layout.addWidget(self._button_box) self.updateGeometry()
def run_tool(self, attacher_class=None, **kwargs): """ Function that launches current tool :param tool_kwargs: dict, dictionary of arguments to launch tool with :return: """ from tpDcc.managers import tools tool_config_dict = self.config_dict() tool_name = tool_config_dict.get('name', None) tool_id = tool_config_dict.get('id', None) tool_size = tool_config_dict.get('size', None) if not tool_name or not tool_id: logger.warning('Impossible to run tool "{}" with id: "{}"'.format( tool_name, tool_id)) return None # Close tool if is already instanced main_window = dcc.get_main_window() if main_window: wins = dcc.get_main_window().findChildren(QWidget, tool_id) or list() for w in wins: w.close() w.deleteLater() # tool_instance = tools.ToolsManager().get_tool_by_plugin_instance() toolset_class = self.TOOLSET_CLASS # toolset_data_copy = copy.deepcopy(self._config.data) # toolset_data_copy.update(toolset_class.CONFIG.data) # toolset_class.CONFIG.data = toolset_data_copy kwargs['collapsable'] = False kwargs['show_item_icon'] = False if not attacher_class: attacher_class = window.Window toolset_inst = None if toolset_class: toolset_inst = toolset_class(**kwargs) toolset_inst.ID = tool_id toolset_inst.CONFIG = tool_config_dict toolset_inst.initialize(client=self._client) # noinspection PyArgumentList self._attacher = attacher_class( id=tool_id, title=self.name, config=self.config, settings=self.settings, show_on_initialize=False, frameless=self.is_frameless, dockable=True, toolset=toolset_inst, icon=resources.icon(tool_config_dict.get('icon', 'tpdcc'))) if toolset_inst: toolset_inst.set_attacher(self._attacher) # self._attacher.setWindowIcon(toolset_inst.get_icon()) self._attacher.setWindowTitle('{} - {}'.format( self._attacher.windowTitle(), self.VERSION)) if tool_size: self._attacher.resize(tool_size[0], tool_size[1]) self._attacher.show() return self._attacher
def __init__(self): super(MessageHandler, self).__init__() self.parent_window = dcc.get_main_window()