Source code for artv2_utilities.interface_utilities

# -*- coding: utf-8 -*-
"""

This module provides utilities for general QT functions and classes to be used as widgets or templates.

Classes
---------

- :class:`ARTv2Message <artv2_utilities.interface_utilities.ARTv2Message>`
- :class:`ARTv2Window <artv2_utilities.interface_utilities.ARTv2Window>`
- :class:`ErrorWidget <artv2_utilities.interface_utilities.ErrorWidget>`
- :class:`InfoWidget <artv2_utilities.interface_utilities.InfoWidget>`

Functions
---------

- :func:`create_style_sheet <artv2_utilities.interface_utilities.create_style_sheet>`
- :func:`get_maya_window <artv2_utilities.interface_utilities.get_maya_window>`
- :func:`get_style_sheet <artv2_utilities.interface_utilities.get_style_sheet>`
- :func:`scale_by_resolution <artv2_utilities.interface_utilities.scale_by_resolution>`

"""

import os

import maya.OpenMayaUI as mui
import maya.cmds as cmds
from maya.app.general.mayaMixin import MayaQWidgetBaseMixin

from third_party.Qt import QtWidgets, QtGui, QtCore
import general_utilities as utils
try:
    import shiboken as shiboken
except ImportError:
    import shiboken2 as shiboken


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs]def get_maya_window(): """ Return Maya's main window as a QWidget""" pointer = mui.MQtUtil.mainWindow() return shiboken.wrapInstance(long(pointer), QtWidgets.QWidget)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs]def scale_by_resolution(width, height, widget): """ Find the screen resolution and adjust the incoming width and height to accomodate. :param width: desired widget width :param height: desired widget height :param widget: widget used to query which monitor to query :return: modified width and height based on screen resolution """ screen = QtWidgets.QDesktopWidget() resolution = screen.availableGeometry(widget) screen_width = float(resolution.width()) screen_height = float(resolution.height()) scale_factor_width = float(screen_width/1920) scale_factor_height = float(screen_height/1080) return [width * scale_factor_width, height * scale_factor_height]
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs]def get_style_sheet(file_path): """ Read the style sheet data, and then replace any urls with proper file paths on the user's drive.""" settings = utils.return_settings() style_sheet_file = utils.path_join(settings[0], "resources/_styleSheets/" + file_path + ".qss") f = open(style_sheet_file, "r") data = f.readlines() style = create_style_sheet(data) f.close() return style
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs]def create_style_sheet(data): """ Take in a read stylesheet, and replace any urls with actual file paths, then return the altered data.""" settings = utils.return_settings() new_lines = [] # todo: could be simplified for line in data: if line.find("url(") != -1: if line.find("resources/icons/backgrounds") != -1: old_path = line.partition("(")[2].rpartition("/")[0] replace_path = utils.path_join(settings[2], "backgrounds") new_line = line.replace(old_path, replace_path) new_lines.append(new_line) if line.find("resources/icons/backgrounds") == -1: old_path = line.partition("(")[2].rpartition("/")[0] replace_path = settings[2] new_line = line.replace(old_path, replace_path) new_lines.append(new_line) else: new_lines.append(line) user_dir = utils.path_unify(os.path.join(settings[0], "user")) if not os.path.exists(user_dir): os.makedirs(user_dir) full_path = (utils.path_join(user_dir, "style.qss")) f = open(full_path, 'w') f.writelines(new_lines) f.close() f = open(full_path, 'r') style = f.read() f.close() os.remove(full_path) return style
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # class ARTv2Message(MayaQWidgetBaseMixin, QtWidgets.QMessageBox): """ Abstract class that adds extra functionality onto QMessageBox. Depending on the message type (warning, error, etc), different buttons and icons will be shown. This class is not meant to be instantiated on its own. """ def __init__(self, width, height, title, critical=False, warning=False, info=False, question=False, parent=None): super(ARTv2Message, self).__init__(parent) if cmds.window(self.WINDOW_NAME, exists=True): cmds.deleteUI(self.WINDOW_NAME) self.setObjectName(self.WINDOW_NAME) self.settings = utils.return_settings() self.tools_path = self.settings[0] self.script_path = self.settings[1] self.icon_path = self.settings[2] self.project_path = self.settings[3] w, h = scale_by_resolution(width, height, self) self.setMinimumSize(QtCore.QSize(w, h)) self.setMaximumSize(QtCore.QSize(w, h)) self.setWindowTitle(title) if critical: self.setIcon(QtWidgets.QMessageBox.Critical) elif warning: self.setIcon(QtWidgets.QMessageBox.Warning) elif info: self.setIcon(QtWidgets.QMessageBox.Information) elif question: self.setIcon(QtWidgets.QMessageBox.Question) else: self.setIcon(QtWidgets.QMessageBox.NoIcon) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # class ARTv2Window(MayaQWidgetBaseMixin, QtWidgets.QMainWindow): """ Abstract class that adds some extra default functionality for things like grabbing settings, dealing with different screen resolutions, styling the UI, and saving screen position. This class is not meant to be instantiated on its own. """ def __init__(self, width, height, window_title, parent=None): super(ARTv2Window, self).__init__(parent) if cmds.window(self.WINDOW_NAME, exists=True): cmds.deleteUI(self.WINDOW_NAME) self.setObjectName(self.WINDOW_NAME) self.settings = utils.return_settings() self.tools_path = self.settings[0] self.script_path = self.settings[1] self.icon_path = self.settings[2] self.project_path = self.settings[3] w, h = scale_by_resolution(width, height, self) self.setMinimumSize(QtCore.QSize(w, h)) self.setMaximumSize(QtCore.QSize(w, h)) style_sheet = get_style_sheet("artv2_style") self.setStyleSheet(style_sheet) self.setWindowTitle(window_title) window_icon = QtGui.QIcon(os.path.join(self.icon_path, "general/logo.png")) self.setWindowIcon(window_icon) self.restoreGeometry(self.settings[4].value(self.SETTINGS_NAME)) # noinspection PyPep8Naming def closeEvent(self, event): """ Override QMainWindow's close event to remember window position.""" self.settings[4].setValue(self.SETTINGS_NAME, self.saveGeometry()) QtWidgets.QMainWindow.closeEvent(self, event) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs]class ErrorWidget(ARTv2Message): """ Simple class that displays a QMessageBox widget with an error message, and error icon, and a simple "OK" button. Takes in a string message to display. .. image:: /images/errorWidget.png """ SETTINGS_NAME = "ARTv2ErrorWidget" WINDOW_NAME = "artv2_error_message_window" def __init__(self, message, parent=None): super(ErrorWidget, self).__init__(300, 150, "Error", critical=True, parent=parent) self.setText(message)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
[docs]class InfoWidget(ARTv2Message): """ Simple class that displays a QMessageBox widget with an error message, and error icon, and a simple "OK" button. This class takes in required arguments: A string message, and a string for details. The details string could be empty if not required. .. code-block:: python message = ui_utils.InfoWidget("this is an info widget", "these are some details\\nas are these") .. image:: /images/infoWidget.png """ SETTINGS_NAME = "ARTv2InfoWidget" WINDOW_NAME = "artv2_info_message_window" def __init__(self, message, details, parent=None): super(InfoWidget, self).__init__(300, 200, "Attention!", info=True, parent=parent) self.setText(message) self.setDetailedText(details)