Merge develop - resolve conflict

This commit is contained in:
Petr Kalis 2021-03-10 17:56:19 +01:00
commit 22883b840c
24 changed files with 1386 additions and 917 deletions

View file

@ -7,7 +7,7 @@ from maya import utils, cmds
from avalon import api as avalon
from avalon import pipeline
from avalon.maya import suspended_refresh
from avalon.maya.pipeline import IS_HEADLESS, _on_task_changed
from avalon.maya.pipeline import IS_HEADLESS
from avalon.tools import workfiles
from pyblish import api as pyblish
from pype.lib import any_outdated
@ -45,9 +45,7 @@ def install():
avalon.on("open", on_open)
avalon.on("new", on_new)
avalon.before("save", on_before_save)
log.info("Overriding existing event 'taskChanged'")
override_event("taskChanged", on_task_changed)
avalon.on("taskChanged", on_task_changed)
log.info("Setting default family states for loader..")
avalon.data["familiesStateToggled"] = ["imagesequence"]
@ -61,24 +59,6 @@ def uninstall():
menu.uninstall()
def override_event(event, callback):
"""
Override existing event callback
Args:
event (str): name of the event
callback (function): callback to be triggered
Returns:
None
"""
ref = weakref.WeakSet()
ref.add(callback)
pipeline._registered_event_handlers[event] = ref
def on_init(_):
avalon.logger.info("Running callback on init..")
@ -215,7 +195,6 @@ def on_new(_):
def on_task_changed(*args):
"""Wrapped function of app initialize and maya's on task changed"""
# Run
_on_task_changed()
with suspended_refresh():
lib.set_context_settings()
lib.update_content_on_context_change()

View file

@ -72,7 +72,7 @@ class GenerateUUIDsOnInvalidAction(pyblish.api.Action):
nodes (list): all nodes to regenerate ids on
"""
from pype.hosts.maya import lib
from pype.hosts.maya.api import lib
import avalon.io as io
asset = instance.data['asset']

View file

@ -2127,15 +2127,9 @@ def bake_to_world_space(nodes,
def load_capture_preset(path=None, data=None):
import capture_gui
import capture
if data:
preset = data
else:
path = path
preset = capture_gui.lib.load_json(path)
print(preset)
preset = data
options = dict()
@ -2177,29 +2171,27 @@ def load_capture_preset(path=None, data=None):
temp_options2 = {}
id = 'Viewport Options'
light_options = {
0: "default",
1: 'all',
2: 'selected',
3: 'flat',
4: 'nolights'}
for key in preset[id]:
if key == 'high_quality':
if preset[id][key] == True:
temp_options2['multiSampleEnable'] = True
temp_options2['multiSampleCount'] = 4
temp_options2['textureMaxResolution'] = 1024
if key == 'textureMaxResolution':
if preset[id][key] > 0:
temp_options2['textureMaxResolution'] = preset[id][key]
temp_options2['enableTextureMaxRes'] = True
temp_options2['textureMaxResMode'] = 1
else:
temp_options2['multiSampleEnable'] = False
temp_options2['multiSampleCount'] = 4
temp_options2['textureMaxResolution'] = 512
temp_options2['enableTextureMaxRes'] = True
temp_options2['textureMaxResolution'] = preset[id][key]
temp_options2['enableTextureMaxRes'] = False
temp_options2['textureMaxResMode'] = 0
if key == 'multiSample':
if preset[id][key] > 0:
temp_options2['multiSampleEnable'] = True
temp_options2['multiSampleCount'] = preset[id][key]
else:
temp_options2['multiSampleEnable'] = False
temp_options2['multiSampleCount'] = preset[id][key]
if key == 'ssaoEnable':
if preset[id][key] == True:
if preset[id][key] is True:
temp_options2['ssaoEnable'] = True
else:
temp_options2['ssaoEnable'] = False
@ -2211,18 +2203,17 @@ def load_capture_preset(path=None, data=None):
if key == 'headsUpDisplay':
temp_options['headsUpDisplay'] = True
if key == 'displayLights':
temp_options[str(key)] = light_options[preset[id][key]]
else:
temp_options[str(key)] = preset[id][key]
for key in ['override_viewport_options',
'high_quality',
'alphaCut',
'gpuCacheDisplayFilter']:
temp_options.pop(key, None)
for key in ['ssaoEnable']:
'gpuCacheDisplayFilter',
'multiSample',
'ssaoEnable',
'textureMaxResolution'
]:
temp_options.pop(key, None)
options['viewport_options'] = temp_options
@ -2686,7 +2677,7 @@ def update_content_on_context_change():
def show_message(title, msg):
from avalon.vendor.Qt import QtWidgets
from ...widgets import message_window
from pype.widgets import message_window
# Find maya main window
top_level_widgets = {w.objectName(): w for w in

View file

@ -23,6 +23,7 @@ class ExtractPlayblast(pype.api.Extractor):
hosts = ["maya"]
families = ["review"]
optional = True
capture_preset = {}
def process(self, instance):
self.log.info("Extracting capture..")
@ -43,15 +44,9 @@ class ExtractPlayblast(pype.api.Extractor):
# get cameras
camera = instance.data['review_camera']
capture_preset = (
instance.context.data['project_settings']['maya']['capture']
)
try:
preset = lib.load_capture_preset(data=capture_preset)
except Exception:
preset = {}
self.log.info('using viewport preset: {}'.format(preset))
preset = lib.load_capture_preset(data=self.capture_preset)
preset['camera'] = camera
preset['format'] = "image"
@ -101,6 +96,9 @@ class ExtractPlayblast(pype.api.Extractor):
# Remove panel key since it's internal value to capture_gui
preset.pop("panel", None)
self.log.info('using viewport preset: {}'.format(preset))
path = capture.capture(**preset)
playblast = self._fix_playblast_output_path(path)

View file

@ -34,7 +34,7 @@ class ExtractThumbnail(pype.api.Extractor):
capture_preset = ""
capture_preset = (
instance.context.data["project_settings"]['maya']['capture']
instance.context.data["project_settings"]['maya']['publish']['ExtractPlayblast']
)
try:

View file

@ -95,6 +95,7 @@ class LoadMov(api.Loader):
containerise,
viewer_update_and_undo_stop
)
version = context['version']
version_data = version.get("data", {})
repr_id = context["representation"]["_id"]

View file

@ -73,5 +73,17 @@ class CreateImage(pype.api.Creator):
groups.append(group)
for group in groups:
long_names = []
if group.long_name:
for directory in group.long_name[::-1]:
name = directory.replace(stub.PUBLISH_ICON, '').\
replace(stub.LOADED_ICON, '')
long_names.append(name)
self.data.update({"subset": "image" + group.name})
self.data.update({"uuid": str(group.id)})
self.data.update({"long_name": "_".join(long_names)})
stub.imprint(group, self.data)
# reusing existing group, need to rename afterwards
if not create_group:
stub.rename_layer(group.id, stub.PUBLISH_ICON + group.name)

View file

@ -24,6 +24,7 @@ class CollectInstances(pyblish.api.ContextPlugin):
stub = photoshop.stub()
layers = stub.get_layers()
layers_meta = stub.get_layers_metadata()
instance_names = []
for layer in layers:
layer_data = stub.read(layer, layers_meta)
@ -41,14 +42,20 @@ class CollectInstances(pyblish.api.ContextPlugin):
# self.log.info("%s skipped, it was empty." % layer.Name)
# continue
instance = context.create_instance(layer.name)
instance = context.create_instance(layer_data["subset"])
instance.append(layer)
instance.data.update(layer_data)
instance.data["families"] = self.families_mapping[
layer_data["family"]
]
instance.data["publish"] = layer.visible
instance_names.append(layer_data["subset"])
# Produce diagnostic message for any graphical
# user interface interested in visualising it.
self.log.info("Found: \"%s\" " % instance.data["name"])
self.log.info("instance: {} ".format(instance.data))
if len(instance_names) != len(set(instance_names)):
self.log.warning("Duplicate instances found. " +
"Remove unwanted via SubsetManager")

View file

@ -25,11 +25,15 @@ class ValidateNamingRepair(pyblish.api.Action):
for instance in instances:
self.log.info("validate_naming instance {}".format(instance))
name = instance.data["name"].replace(" ", "_")
name = name.replace(instance.data["family"], '')
instance[0].Name = name
data = stub.read(instance[0])
data["subset"] = "image" + name
stub.imprint(instance[0], data)
name = stub.PUBLISH_ICON + name
stub.rename_layer(instance.data["uuid"], name)
return True
@ -46,8 +50,11 @@ class ValidateNaming(pyblish.api.InstancePlugin):
actions = [ValidateNamingRepair]
def process(self, instance):
msg = "Name \"{}\" is not allowed.".format(instance.data["name"])
help_msg = ' Use Repair action (A) in Pyblish to fix it.'
msg = "Name \"{}\" is not allowed.{}".format(instance.data["name"],
help_msg)
assert " " not in instance.data["name"], msg
msg = "Subset \"{}\" is not allowed.".format(instance.data["subset"])
msg = "Subset \"{}\" is not allowed.{}".format(instance.data["subset"],
help_msg)
assert " " not in instance.data["subset"], msg

View file

@ -0,0 +1,26 @@
import pyblish.api
import pype.api
class ValidateSubsetUniqueness(pyblish.api.ContextPlugin):
"""
Validate that all subset's names are unique.
"""
label = "Validate Subset Uniqueness"
hosts = ["photoshop"]
order = pype.api.ValidateContentsOrder
families = ["image"]
def process(self, context):
subset_names = []
for instance in context:
if instance.data.get('publish'):
subset_names.append(instance.data.get('subset'))
msg = (
"Instance subset names are not unique. " +
"Remove duplicates via SubsetManager."
)
assert len(subset_names) == len(set(subset_names)), msg

87
pype/lib/pype_info.py Normal file
View file

@ -0,0 +1,87 @@
import os
import json
import datetime
import platform
import getpass
import socket
import pype.version
from pype.settings.lib import get_local_settings
from .execute import get_pype_execute_args
from .local_settings import get_local_site_id
def get_pype_version():
"""Version of pype that is currently used."""
return pype.version.__version__
def get_pype_info():
"""Information about currently used Pype process."""
executable_args = get_pype_execute_args()
if len(executable_args) == 1:
version_type = "build"
else:
version_type = "code"
return {
"version": get_pype_version(),
"version_type": version_type,
"executable": executable_args[-1],
"pype_root": os.environ["PYPE_ROOT"],
"mongo_url": os.environ["PYPE_MONGO"]
}
def get_workstation_info():
"""Basic information about workstation."""
host_name = socket.gethostname()
try:
host_ip = socket.gethostbyname(host_name)
except socket.gaierror:
host_ip = "127.0.0.1"
return {
"hostname": host_name,
"hostip": host_ip,
"username": getpass.getuser(),
"system_name": platform.system(),
"local_id": get_local_site_id()
}
def get_all_current_info():
"""All information about current process in one dictionary."""
return {
"pype": get_pype_info(),
"workstation": get_workstation_info(),
"env": os.environ.copy(),
"local_settings": get_local_settings()
}
def extract_pype_info_to_file(dirpath):
"""Extract all current info to a file.
It is possible to define onpy directory path. Filename is concatenated with
pype version, workstation site id and timestamp.
Args:
dirpath (str): Path to directory where file will be stored.
Returns:
filepath (str): Full path to file where data were extracted.
"""
filename = "{}_{}_{}.json".format(
get_pype_version(),
get_local_site_id(),
datetime.datetime.now().strftime("%y%m%d%H%M%S")
)
filepath = os.path.join(dirpath, filename)
data = get_all_current_info()
if not os.path.exists(dirpath):
os.makedirs(dirpath)
with open(filepath, "w") as file_stream:
json.dump(data, file_stream, indent=4)
return filepath

View file

@ -108,6 +108,7 @@ class ITrayModule:
would do nothing.
"""
tray_initialized = False
_tray_manager = None
@abstractmethod
def tray_init(self):
@ -138,6 +139,20 @@ class ITrayModule:
"""
pass
def show_tray_message(self, title, message, icon=None, msecs=None):
"""Show tray message.
Args:
title (str): Title of message.
message (str): Content of message.
icon (QSystemTrayIcon.MessageIcon): Message's icon. Default is
Information icon, may differ by Qt version.
msecs (int): Duration of message visibility in miliseconds.
Default is 10000 msecs, may differ by Qt version.
"""
if self._tray_manager:
self._tray_manager.show_tray_message(title, message, icon, msecs)
class ITrayAction(ITrayModule):
"""Implementation of Tray action.
@ -638,8 +653,10 @@ class TrayModulesManager(ModulesManager):
self.modules_by_id = {}
self.modules_by_name = {}
self._report = {}
self.tray_manager = None
def initialize(self, tray_menu):
def initialize(self, tray_manager, tray_menu):
self.tray_manager = tray_manager
self.initialize_modules()
self.tray_init()
self.connect_modules()
@ -658,6 +675,7 @@ class TrayModulesManager(ModulesManager):
prev_start_time = time_start
for module in self.get_enabled_tray_modules():
try:
module._tray_manager = self.tray_manager
module.tray_init()
module.tray_initialized = True
except Exception:

View file

@ -1,17 +0,0 @@
<svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="312px" height="312px" viewBox="0 0 40 40" xml:space="preserve">
<path opacity="0.2" fill="#ffa500" d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946
s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634
c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z"/>
<path fill="#ffa500" d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0
C22.32,8.481,24.301,9.057,26.013,10.047z">
<animateTransform attributeType="xml"
attributeName="transform"
type="rotate"
from="00 20.2 20.1"
to="360 20.2 20.1"
dur="0.5s"
repeatCount="indefinite"/>
</path>
<text x="3" y="23" fill="#ffa500" font-style="bold" font-size="7px" font-family="sans-serif">Working...</text>
</svg>

Before

Width:  |  Height:  |  Size: 1 KiB

View file

@ -1,111 +1,11 @@
{
"capture": {
"Codec": {
"compression": "jpg",
"format": "image",
"quality": 95
},
"Display Options": {
"background": [
0.7,
0.7,
0.7
],
"backgroundBottom": [
0.7,
0.7,
0.7
],
"backgroundTop": [
0.7,
0.7,
0.7
],
"override_display": true
},
"Generic": {
"isolate_view": true,
"off_screen": true
},
"IO": {
"name": "",
"open_finished": true,
"raw_frame_numbers": true,
"recent_playblasts": [],
"save_file": true
},
"PanZoom": {
"pan_zoom": true
},
"Renderer": {
"rendererName": "vp2Renderer"
},
"Resolution": {
"width": 1080,
"height": 1920,
"percent": 1.0,
"mode": "Custom"
},
"Time Range": {
"start_frame": 0,
"end_frame": 0,
"frame": "",
"time": "Time Slider"
},
"Viewport Options": {
"cameras": false,
"clipGhosts": false,
"controlVertices": false,
"deformers": false,
"dimensions": false,
"displayLights": 0,
"dynamicConstraints": false,
"dynamics": false,
"fluids": false,
"follicles": false,
"gpuCacheDisplayFilter": false,
"greasePencils": false,
"grid": false,
"hairSystems": true,
"handles": false,
"high_quality": true,
"hud": false,
"hulls": false,
"ikHandles": false,
"imagePlane": true,
"joints": false,
"lights": false,
"locators": false,
"manipulators": false,
"motionTrails": false,
"nCloths": false,
"nParticles": false,
"nRigids": false,
"nurbsCurves": false,
"nurbsSurfaces": false,
"override_viewport_options": true,
"particleInstancers": false,
"pivots": false,
"planes": false,
"pluginShapes": false,
"polymeshes": true,
"shadows": true,
"strokes": false,
"subdivSurfaces": false,
"textures": false,
"twoSidedLighting": true
},
"Camera Options": {
"displayGateMask": false,
"displayResolution": false,
"displayFilmGate": false,
"displayFieldChart": false,
"displaySafeAction": false,
"displaySafeTitle": false,
"displayFilmPivot": false,
"displayFilmOrigin": false,
"overscan": 1.0
}
"ext_mapping": {
"model": "ma",
"mayaAscii": "ma",
"camera": "ma",
"rig": "ma",
"workfile": "ma",
"yetiRig": "ma"
},
"create": {
"CreateAnimation": {
@ -299,6 +199,10 @@
"enabled": false,
"optional": true
},
"ValidateMeshNormalsUnlocked": {
"enabled": false,
"optional": true
},
"ValidateMeshUVSetMap1": {
"enabled": false,
"optional": true
@ -336,7 +240,7 @@
"optional": true
},
"ValidateTransformZero": {
"enabled": true,
"enabled": false,
"optional": true
},
"ValidateCameraAttributes": {
@ -351,6 +255,105 @@
"enabled": true,
"optional": true
},
"ExtractPlayblast": {
"capture_preset": {
"Codec": {
"compression": "jpg",
"format": "image",
"quality": 95
},
"Display Options": {
"background": [
0.7,
0.7,
0.7
],
"backgroundBottom": [
0.7,
0.7,
0.7
],
"backgroundTop": [
0.7,
0.7,
0.7
],
"override_display": true
},
"Generic": {
"isolate_view": true,
"off_screen": true
},
"PanZoom": {
"pan_zoom": true
},
"Renderer": {
"rendererName": "vp2Renderer"
},
"Resolution": {
"width": 1080,
"height": 1920,
"percent": 1.0,
"mode": "Custom"
},
"Viewport Options": {
"override_viewport_options": true,
"displayLights": "0",
"textureMaxResolution": 1024,
"multiSample": 4,
"shadows": true,
"textures": true,
"twoSidedLighting": true,
"ssaoEnable": true,
"cameras": false,
"clipGhosts": false,
"controlVertices": false,
"deformers": false,
"dimensions": false,
"dynamicConstraints": false,
"dynamics": false,
"fluids": false,
"follicles": false,
"gpuCacheDisplayFilter": false,
"greasePencils": false,
"grid": false,
"hairSystems": true,
"handles": false,
"hud": false,
"hulls": false,
"ikHandles": false,
"imagePlane": true,
"joints": false,
"lights": false,
"locators": false,
"manipulators": false,
"motionTrails": false,
"nCloths": false,
"nParticles": false,
"nRigids": false,
"nurbsCurves": false,
"nurbsSurfaces": false,
"particleInstancers": false,
"pivots": false,
"planes": false,
"pluginShapes": false,
"polymeshes": true,
"strokes": false,
"subdivSurfaces": false
},
"Camera Options": {
"displayGateMask": false,
"displayResolution": false,
"displayFilmGate": false,
"displayFieldChart": false,
"displaySafeAction": false,
"displaySafeTitle": false,
"displayFilmPivot": false,
"displayFilmOrigin": false,
"overscan": 1.0
}
}
},
"ExtractCameraAlembic": {
"enabled": true,
"optional": true,

View file

@ -11,6 +11,30 @@
"PreCollectNukeInstances": {
"sync_workfile_version": true
},
"ValidateKnobs": {
"enabled": false,
"knobs": {
"render": {
"review": true
}
}
},
"ValidateOutputResolution": {
"enabled": true,
"optional": true
},
"ValidateGizmo": {
"enabled": true,
"optional": true
},
"ValidateScript": {
"enabled": true,
"optional": true
},
"ValidateNukeWriteBoundingBox": {
"enabled": true,
"optional": true
},
"ExtractThumbnail": {
"enabled": true,
"nodes": {
@ -38,14 +62,6 @@
]
}
},
"ValidateKnobs": {
"enabled": false,
"knobs": {
"render": {
"review": true
}
}
},
"ExtractReviewDataLut": {
"enabled": false
},
@ -61,22 +77,25 @@
"deadline_pool": "",
"deadline_pool_secondary": "",
"deadline_chunk_size": 1
},
"ValidateOutputResolution": {
}
},
"load": {
"LoadImage": {
"enabled": true,
"optional": true
"representations": []
},
"ValidateGizmo": {
"LoadMov": {
"enabled": true,
"optional": true
"representations": []
},
"ValidateScript": {
"LoadSequence": {
"enabled": true,
"optional": true
},
"ValidateNukeWriteBoundingBox": {
"enabled": true,
"optional": true
"representations": [
"png",
"jpg",
"exr",
""
]
}
},
"workfile_build": {

View file

@ -1,14 +1,4 @@
{
"publish": {
"ExtractThumbnailSP": {
"ffmpeg_args": {
"input": [
"gamma 2.2"
],
"output": []
}
}
},
"create": {
"create_workfile": {
"name": "workfile",
@ -121,5 +111,15 @@
"create_image": "Image",
"create_matchmove": "Matchmove"
}
},
"publish": {
"ExtractThumbnailSP": {
"ffmpeg_args": {
"input": [
"gamma 2.2"
],
"output": []
}
}
}
}

View file

@ -6,8 +6,13 @@
"is_file": true,
"children": [
{
"type": "schema",
"name": "schema_maya_capture"
"type": "dict-modifiable",
"key": "ext_mapping",
"label": "Extension Mapping",
"use_label_wrap": true,
"object_type": {
"type": "text"
}
},
{
"type": "schema",

View file

@ -45,6 +45,11 @@
"type": "schema",
"name": "schema_nuke_publish",
"template_data": []
},
{
"type": "schema",
"name": "schema_nuke_load",
"template_data": []
},
{
"type": "schema",

View file

@ -1,581 +0,0 @@
{
"type": "dict",
"collapsible": true,
"key": "capture",
"label": "Maya Playblast settings",
"is_file": true,
"children": [
{
"type": "dict",
"key": "Codec",
"children": [
{
"type": "label",
"label": "<b>Codec</b>"
},
{
"type": "text",
"key": "compression",
"label": "Compression type"
},
{
"type": "text",
"key": "format",
"label": "Data format"
},
{
"type": "number",
"key": "quality",
"label": "Quality",
"decimal": 0,
"minimum": 0,
"maximum": 100
},
{
"type": "splitter"
}
]
},
{
"type": "dict",
"key": "Display Options",
"children": [
{
"type": "label",
"label": "<b>Display Options</b>"
},
{
"type": "list-strict",
"key": "background",
"label": "Background Color: ",
"object_types": [
{
"label": "Red",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Green",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Blue",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
}
]
},
{
"type": "list-strict",
"key": "backgroundBottom",
"label": "Background Bottom: ",
"object_types": [
{
"label": "Red",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Green",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Blue",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
}
]
},
{
"type": "list-strict",
"key": "backgroundTop",
"label": "Background Top: ",
"object_types": [
{
"label": "Red",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Green",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Blue",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
}
]
},
{
"type": "boolean",
"key": "override_display",
"label": "Override display options"
}
]
},
{
"type": "splitter"
},
{
"type": "dict",
"key": "Generic",
"children": [
{
"type": "label",
"label": "<b>Generic</b>"
},
{
"type": "boolean",
"key": "isolate_view",
"label": " Isolate view"
},
{
"type": "boolean",
"key": "off_screen",
"label": " Off Screen"
}
]
},
{
"type": "dict",
"key": "IO",
"children": [
{
"type": "label",
"label": "<b>IO</b>"
},
{
"type": "text",
"key": "name",
"label": "Name"
},
{
"type": "boolean",
"key": "open_finished",
"label": "Open finished"
},
{
"type": "boolean",
"key": "raw_frame_numbers",
"label": "Raw frame numbers"
},
{
"type": "list",
"key": "recent_playblasts",
"label": "Recent Playblasts",
"object_type": "text"
},
{
"type": "boolean",
"key": "save_file",
"label": "Save file"
}
]
},
{
"type": "dict",
"key": "PanZoom",
"children": [
{
"type": "boolean",
"key": "pan_zoom",
"label": " Pan Zoom"
}
]
},
{
"type": "splitter"
},
{
"type": "dict",
"key": "Renderer",
"children": [
{
"type": "label",
"label": "<b>Renderer</b>"
},
{
"type": "text",
"key": "rendererName",
"label": " Renderer name"
}
]
},
{
"type": "dict",
"key": "Resolution",
"children": [
{
"type": "splitter"
},
{
"type": "label",
"label": "<b>Resolution</b>"
},
{
"type": "number",
"key": "width",
"label": " Width",
"decimal": 0,
"minimum": 0,
"maximum": 99999
},
{
"type": "number",
"key": "height",
"label": "Height",
"decimal": 0,
"minimum": 0,
"maximum": 99999
},
{
"type": "number",
"key": "percent",
"label": "percent",
"decimal": 1,
"minimum": 0,
"maximum": 200
},
{
"type": "text",
"key": "mode",
"label": "Mode"
}
]
},
{
"type": "splitter"
},
{
"type": "dict",
"key": "Time Range",
"children": [
{
"type": "label",
"label": "<b>Time Range</b>"
},
{
"type": "number",
"key": "start_frame",
"label": " Start frame",
"decimal": 0,
"minimum": 0,
"maximum": 999999
},
{
"type": "number",
"key": "end_frame",
"label": "End frame",
"decimal": 0,
"minimum": 0,
"maximum": 999999
},
{
"type": "text",
"key": "frame",
"label": "Frame"
},
{
"type": "text",
"key": "time",
"label": "Time"
}
]
},
{
"type": "dict",
"collapsible": true,
"key": "Viewport Options",
"label": "Viewport Options",
"children": [
{
"type": "boolean",
"key": "cameras",
"label": "cameras"
},
{
"type": "boolean",
"key": "clipGhosts",
"label": "clipGhosts"
},
{
"type": "boolean",
"key": "controlVertices",
"label": "controlVertices"
},
{
"type": "boolean",
"key": "deformers",
"label": "deformers"
},
{
"type": "boolean",
"key": "dimensions",
"label": "dimensions"
},
{
"type": "number",
"key": "displayLights",
"label": "displayLights",
"decimal": 0,
"minimum": 0,
"maximum": 10
},
{
"type": "boolean",
"key": "dynamicConstraints",
"label": "dynamicConstraints"
},
{
"type": "boolean",
"key": "dynamics",
"label": "dynamics"
},
{
"type": "boolean",
"key": "fluids",
"label": "fluids"
},
{
"type": "boolean",
"key": "follicles",
"label": "follicles"
},
{
"type": "boolean",
"key": "gpuCacheDisplayFilter",
"label": "gpuCacheDisplayFilter"
},
{
"type": "boolean",
"key": "greasePencils",
"label": "greasePencils"
},
{
"type": "boolean",
"key": "grid",
"label": "grid"
},
{
"type": "boolean",
"key": "hairSystems",
"label": "hairSystems"
},
{
"type": "boolean",
"key": "handles",
"label": "handles"
},
{
"type": "boolean",
"key": "high_quality",
"label": "high_quality"
},
{
"type": "boolean",
"key": "hud",
"label": "hud"
},
{
"type": "boolean",
"key": "hulls",
"label": "hulls"
},
{
"type": "boolean",
"key": "ikHandles",
"label": "ikHandles"
},
{
"type": "boolean",
"key": "imagePlane",
"label": "imagePlane"
},
{
"type": "boolean",
"key": "joints",
"label": "joints"
},
{
"type": "boolean",
"key": "lights",
"label": "lights"
},
{
"type": "boolean",
"key": "locators",
"label": "locators"
},
{
"type": "boolean",
"key": "manipulators",
"label": "manipulators"
},
{
"type": "boolean",
"key": "motionTrails",
"label": "motionTrails"
},
{
"type": "boolean",
"key": "nCloths",
"label": "nCloths"
},
{
"type": "boolean",
"key": "nParticles",
"label": "nParticles"
},
{
"type": "boolean",
"key": "nRigids",
"label": "nRigids"
},
{
"type": "boolean",
"key": "nurbsCurves",
"label": "nurbsCurves"
},
{
"type": "boolean",
"key": "nurbsSurfaces",
"label": "nurbsSurfaces"
},
{
"type": "boolean",
"key": "override_viewport_options",
"label": "override_viewport_options"
},
{
"type": "boolean",
"key": "particleInstancers",
"label": "particleInstancers"
},
{
"type": "boolean",
"key": "pivots",
"label": "pivots"
},
{
"type": "boolean",
"key": "planes",
"label": "planes"
},
{
"type": "boolean",
"key": "pluginShapes",
"label": "pluginShapes"
},
{
"type": "boolean",
"key": "polymeshes",
"label": "polymeshes"
},
{
"type": "boolean",
"key": "shadows",
"label": "shadows"
},
{
"type": "boolean",
"key": "strokes",
"label": "strokes"
},
{
"type": "boolean",
"key": "subdivSurfaces",
"label": "subdivSurfaces"
},
{
"type": "boolean",
"key": "textures",
"label": "textures"
},
{
"type": "boolean",
"key": "twoSidedLighting",
"label": "twoSidedLighting"
}
]
},
{
"type": "dict",
"collapsible": true,
"key": "Camera Options",
"label": "Camera Options",
"children": [
{
"type": "boolean",
"key": "displayGateMask",
"label": "displayGateMask"
},
{
"type": "boolean",
"key": "displayResolution",
"label": "displayResolution"
},
{
"type": "boolean",
"key": "displayFilmGate",
"label": "displayFilmGate"
},
{
"type": "boolean",
"key": "displayFieldChart",
"label": "displayFieldChart"
},
{
"type": "boolean",
"key": "displaySafeAction",
"label": "displaySafeAction"
},
{
"type": "boolean",
"key": "displaySafeTitle",
"label": "displaySafeTitle"
},
{
"type": "boolean",
"key": "displayFilmPivot",
"label": "displayFilmPivot"
},
{
"type": "boolean",
"key": "displayFilmOrigin",
"label": "displayFilmOrigin"
},
{
"type": "number",
"key": "overscan",
"label": "overscan",
"decimal": 1,
"minimum": 0,
"maximum": 10
}
]
}
]
}

View file

@ -170,6 +170,10 @@
"key": "ValidateMeshNonManifold",
"label": "ValidateMeshNonManifold"
},
{
"key": "ValidateMeshNormalsUnlocked",
"label": "ValidateMeshNormalsUnlocked"
},
{
"key": "ValidateMeshUVSetMap1",
"label": "ValidateMeshUVSetMap1",
@ -242,6 +246,10 @@
"type": "label",
"label": "Extractors"
},
{
"type": "schema_template",
"name": "template_maya_capture"
},
{
"type": "dict",
"collapsible": true,

View file

@ -0,0 +1,26 @@
{
"type": "dict",
"collapsible": true,
"key": "load",
"label": "Loader plugins",
"children": [
{
"type": "schema_template",
"name": "template_loader_plugin",
"template_data": [
{
"key": "LoadImage",
"label": "Image Loader"
},
{
"key": "LoadMov",
"label": "Movie Loader"
},
{
"key": "LoadSequence",
"label": "Image Sequence Loader"
}
]
}
]
}

View file

@ -0,0 +1,541 @@
[
{
"type": "dict",
"collapsible": true,
"key": "ExtractPlayblast",
"label": "Extract Playblast settings",
"children": [
{
"type": "dict",
"key": "capture_preset",
"children": [
{
"type": "dict",
"key": "Codec",
"children": [
{
"type": "label",
"label": "<b>Codec</b>"
},
{
"type": "text",
"key": "compression",
"label": "Compression type"
},
{
"type": "text",
"key": "format",
"label": "Data format"
},
{
"type": "number",
"key": "quality",
"label": "Quality",
"decimal": 0,
"minimum": 0,
"maximum": 100
},
{
"type": "splitter"
}
]
},
{
"type": "dict",
"key": "Display Options",
"children": [
{
"type": "label",
"label": "<b>Display Options</b>"
},
{
"type": "list-strict",
"key": "background",
"label": "Background Color: ",
"object_types": [
{
"label": "Red",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Green",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Blue",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
}
]
},
{
"type": "list-strict",
"key": "backgroundBottom",
"label": "Background Bottom: ",
"object_types": [
{
"label": "Red",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Green",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Blue",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
}
]
},
{
"type": "list-strict",
"key": "backgroundTop",
"label": "Background Top: ",
"object_types": [
{
"label": "Red",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Green",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
},
{
"label": "Blue",
"type": "number",
"minimum": 0,
"maximum": 1,
"decimal": 3
}
]
},
{
"type": "boolean",
"key": "override_display",
"label": "Override display options"
}
]
},
{
"type": "splitter"
},
{
"type": "dict",
"key": "Generic",
"children": [
{
"type": "label",
"label": "<b>Generic</b>"
},
{
"type": "boolean",
"key": "isolate_view",
"label": " Isolate view"
},
{
"type": "boolean",
"key": "off_screen",
"label": " Off Screen"
}
]
},
{
"type": "dict",
"key": "PanZoom",
"children": [
{
"type": "boolean",
"key": "pan_zoom",
"label": " Pan Zoom"
}
]
},
{
"type": "splitter"
},
{
"type": "dict",
"key": "Renderer",
"children": [
{
"type": "label",
"label": "<b>Renderer</b>"
},
{
"type": "enum",
"key": "rendererName",
"label": "Renderer name",
"enum_items": [
{ "vp2Renderer": "Viewport 2.0" }
]
}
]
},
{
"type": "dict",
"key": "Resolution",
"children": [
{
"type": "splitter"
},
{
"type": "label",
"label": "<b>Resolution</b>"
},
{
"type": "number",
"key": "width",
"label": " Width",
"decimal": 0,
"minimum": 0,
"maximum": 99999
},
{
"type": "number",
"key": "height",
"label": "Height",
"decimal": 0,
"minimum": 0,
"maximum": 99999
},
{
"type": "number",
"key": "percent",
"label": "percent",
"decimal": 1,
"minimum": 0,
"maximum": 200
},
{
"type": "text",
"key": "mode",
"label": "Mode"
}
]
},
{
"type": "splitter"
},
{
"type": "dict",
"collapsible": true,
"key": "Viewport Options",
"label": "Viewport Options",
"children": [
{
"type": "boolean",
"key": "override_viewport_options",
"label": "override_viewport_options"
},
{
"type": "enum",
"key": "displayLights",
"label": "Display Lights",
"enum_items": [
{ "default": "Default Lighting"},
{ "all": "All Lights"},
{ "selected": "Selected Lights"},
{ "flat": "Flat Lighting"},
{ "nolights": "No Lights"}
]
},
{
"type": "number",
"key": "textureMaxResolution",
"label": "Texture Clamp Resolution",
"decimal": 0
},
{
"type": "number",
"key": "multiSample",
"label": "Anti Aliasing Samples",
"decimal": 0,
"minimum": 0,
"maximum": 32
},
{
"type": "boolean",
"key": "shadows",
"label": "Display Shadows"
},
{
"type": "boolean",
"key": "textures",
"label": "Display Textures"
},
{
"type": "boolean",
"key": "twoSidedLighting",
"label": "Two Sided Lighting"
},
{
"type": "boolean",
"key": "ssaoEnable",
"label": "Screen Space Ambient Occlusion"
},
{
"type": "splitter"
},
{
"type": "boolean",
"key": "cameras",
"label": "cameras"
},
{
"type": "boolean",
"key": "clipGhosts",
"label": "clipGhosts"
},
{
"type": "boolean",
"key": "controlVertices",
"label": "controlVertices"
},
{
"type": "boolean",
"key": "deformers",
"label": "deformers"
},
{
"type": "boolean",
"key": "dimensions",
"label": "dimensions"
},
{
"type": "boolean",
"key": "dynamicConstraints",
"label": "dynamicConstraints"
},
{
"type": "boolean",
"key": "dynamics",
"label": "dynamics"
},
{
"type": "boolean",
"key": "fluids",
"label": "fluids"
},
{
"type": "boolean",
"key": "follicles",
"label": "follicles"
},
{
"type": "boolean",
"key": "gpuCacheDisplayFilter",
"label": "gpuCacheDisplayFilter"
},
{
"type": "boolean",
"key": "greasePencils",
"label": "greasePencils"
},
{
"type": "boolean",
"key": "grid",
"label": "grid"
},
{
"type": "boolean",
"key": "hairSystems",
"label": "hairSystems"
},
{
"type": "boolean",
"key": "handles",
"label": "handles"
},
{
"type": "boolean",
"key": "hud",
"label": "hud"
},
{
"type": "boolean",
"key": "hulls",
"label": "hulls"
},
{
"type": "boolean",
"key": "ikHandles",
"label": "ikHandles"
},
{
"type": "boolean",
"key": "imagePlane",
"label": "imagePlane"
},
{
"type": "boolean",
"key": "joints",
"label": "joints"
},
{
"type": "boolean",
"key": "lights",
"label": "lights"
},
{
"type": "boolean",
"key": "locators",
"label": "locators"
},
{
"type": "boolean",
"key": "manipulators",
"label": "manipulators"
},
{
"type": "boolean",
"key": "motionTrails",
"label": "motionTrails"
},
{
"type": "boolean",
"key": "nCloths",
"label": "nCloths"
},
{
"type": "boolean",
"key": "nParticles",
"label": "nParticles"
},
{
"type": "boolean",
"key": "nRigids",
"label": "nRigids"
},
{
"type": "boolean",
"key": "nurbsCurves",
"label": "nurbsCurves"
},
{
"type": "boolean",
"key": "nurbsSurfaces",
"label": "nurbsSurfaces"
},
{
"type": "boolean",
"key": "particleInstancers",
"label": "particleInstancers"
},
{
"type": "boolean",
"key": "pivots",
"label": "pivots"
},
{
"type": "boolean",
"key": "planes",
"label": "planes"
},
{
"type": "boolean",
"key": "pluginShapes",
"label": "pluginShapes"
},
{
"type": "boolean",
"key": "polymeshes",
"label": "polymeshes"
},
{
"type": "boolean",
"key": "strokes",
"label": "strokes"
},
{
"type": "boolean",
"key": "subdivSurfaces",
"label": "subdivSurfaces"
}
]
},
{
"type": "dict",
"collapsible": true,
"key": "Camera Options",
"label": "Camera Options",
"children": [
{
"type": "boolean",
"key": "displayGateMask",
"label": "displayGateMask"
},
{
"type": "boolean",
"key": "displayResolution",
"label": "displayResolution"
},
{
"type": "boolean",
"key": "displayFilmGate",
"label": "displayFilmGate"
},
{
"type": "boolean",
"key": "displayFieldChart",
"label": "displayFieldChart"
},
{
"type": "boolean",
"key": "displaySafeAction",
"label": "displaySafeAction"
},
{
"type": "boolean",
"key": "displaySafeTitle",
"label": "displaySafeTitle"
},
{
"type": "boolean",
"key": "displayFilmPivot",
"label": "displayFilmPivot"
},
{
"type": "boolean",
"key": "displayFilmOrigin",
"label": "displayFilmOrigin"
},
{
"type": "number",
"key": "overscan",
"label": "overscan",
"decimal": 1,
"minimum": 0,
"maximum": 10
}
]
}
]
}
]
}
]

View file

@ -0,0 +1,402 @@
import os
import json
import collections
from avalon import style
from Qt import QtCore, QtGui, QtWidgets
from pype.api import resources
from pype.settings.lib import get_local_settings
from pype.lib.pype_info import (
get_all_current_info,
get_pype_info,
get_workstation_info,
extract_pype_info_to_file
)
IS_MAIN_ROLE = QtCore.Qt.UserRole
class EnvironmentValueDelegate(QtWidgets.QStyledItemDelegate):
def createEditor(self, parent, option, index):
edit_widget = QtWidgets.QLineEdit(parent)
edit_widget.setReadOnly(True)
return edit_widget
class EnvironmentsView(QtWidgets.QTreeView):
def __init__(self, parent=None):
super(EnvironmentsView, self).__init__(parent)
model = QtGui.QStandardItemModel()
env = os.environ.copy()
keys = []
values = []
for key in sorted(env.keys()):
key_item = QtGui.QStandardItem(key)
key_item.setFlags(
QtCore.Qt.ItemIsSelectable
| QtCore.Qt.ItemIsEnabled
)
key_item.setData(True, IS_MAIN_ROLE)
keys.append(key_item)
value = env[key]
value_item = QtGui.QStandardItem(value)
value_item.setData(True, IS_MAIN_ROLE)
values.append(value_item)
value_parts = [
part
for part in value.split(os.pathsep) if part
]
if len(value_parts) < 2:
continue
sub_parts = []
for part_value in value_parts:
part_item = QtGui.QStandardItem(part_value)
part_item.setData(False, IS_MAIN_ROLE)
sub_parts.append(part_item)
key_item.appendRows(sub_parts)
model.appendColumn(keys)
model.appendColumn(values)
model.setHorizontalHeaderLabels(["Key", "Value"])
self.setModel(model)
# self.setIndentation(0)
delegate = EnvironmentValueDelegate(self)
self.setItemDelegate(delegate)
self.header().setSectionResizeMode(
0, QtWidgets.QHeaderView.ResizeToContents
)
self.setSelectionMode(QtWidgets.QTreeView.ExtendedSelection)
def get_selection_as_dict(self):
indexes = self.selectionModel().selectedIndexes()
main_mapping = collections.defaultdict(dict)
for index in indexes:
is_main = index.data(IS_MAIN_ROLE)
if not is_main:
continue
row = index.row()
value = index.data(QtCore.Qt.DisplayRole)
if index.column() == 0:
key = "key"
else:
key = "value"
main_mapping[row][key] = value
result = {}
for item in main_mapping.values():
result[item["key"]] = item["value"]
return result
def keyPressEvent(self, event):
if (
event.type() == QtGui.QKeyEvent.KeyPress
and event.matches(QtGui.QKeySequence.Copy)
):
selected_data = self.get_selection_as_dict()
selected_str = json.dumps(selected_data, indent=4)
mime_data = QtCore.QMimeData()
mime_data.setText(selected_str)
QtWidgets.QApplication.instance().clipboard().setMimeData(
mime_data
)
event.accept()
else:
return super(EnvironmentsView, self).keyPressEvent(event)
class ClickableWidget(QtWidgets.QWidget):
clicked = QtCore.Signal()
def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.clicked.emit()
super(ClickableWidget, self).mouseReleaseEvent(event)
class CollapsibleWidget(QtWidgets.QWidget):
def __init__(self, label, parent):
super(CollapsibleWidget, self).__init__(parent)
self.content_widget = None
top_part = ClickableWidget(parent=self)
button_size = QtCore.QSize(5, 5)
button_toggle = QtWidgets.QToolButton(parent=top_part)
button_toggle.setIconSize(button_size)
button_toggle.setArrowType(QtCore.Qt.RightArrow)
button_toggle.setCheckable(True)
button_toggle.setChecked(False)
label_widget = QtWidgets.QLabel(label, parent=top_part)
spacer_widget = QtWidgets.QWidget(top_part)
top_part_layout = QtWidgets.QHBoxLayout(top_part)
top_part_layout.setContentsMargins(0, 0, 0, 5)
top_part_layout.addWidget(button_toggle)
top_part_layout.addWidget(label_widget)
top_part_layout.addWidget(spacer_widget, 1)
label_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground)
spacer_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.button_toggle = button_toggle
self.label_widget = label_widget
top_part.clicked.connect(self._top_part_clicked)
self.button_toggle.clicked.connect(self._btn_clicked)
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.setContentsMargins(0, 0, 0, 0)
main_layout.setSpacing(0)
main_layout.setAlignment(QtCore.Qt.AlignTop)
main_layout.addWidget(top_part)
self.main_layout = main_layout
def set_content_widget(self, content_widget):
content_widget.setVisible(self.button_toggle.isChecked())
self.main_layout.addWidget(content_widget)
self.content_widget = content_widget
def _btn_clicked(self):
self.toggle_content(self.button_toggle.isChecked())
def _top_part_clicked(self):
self.toggle_content()
def toggle_content(self, *args):
if len(args) > 0:
checked = args[0]
else:
checked = not self.button_toggle.isChecked()
arrow_type = QtCore.Qt.RightArrow
if checked:
arrow_type = QtCore.Qt.DownArrow
self.button_toggle.setChecked(checked)
self.button_toggle.setArrowType(arrow_type)
if self.content_widget:
self.content_widget.setVisible(checked)
self.parent().updateGeometry()
def resizeEvent(self, event):
super(CollapsibleWidget, self).resizeEvent(event)
if self.content_widget:
self.content_widget.updateGeometry()
class PypeInfoWidget(QtWidgets.QWidget):
not_applicable = "N/A"
def __init__(self, parent=None):
super(PypeInfoWidget, self).__init__(parent)
self.setStyleSheet(style.load_stylesheet())
icon = QtGui.QIcon(resources.pype_icon_filepath())
self.setWindowIcon(icon)
self.setWindowTitle("Pype info")
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.setAlignment(QtCore.Qt.AlignTop)
main_layout.addWidget(self._create_pype_info_widget(), 0)
main_layout.addWidget(self._create_separator(), 0)
main_layout.addWidget(self._create_workstation_widget(), 0)
main_layout.addWidget(self._create_separator(), 0)
main_layout.addWidget(self._create_local_settings_widget(), 0)
main_layout.addWidget(self._create_separator(), 0)
main_layout.addWidget(self._create_environ_widget(), 1)
main_layout.addWidget(self._create_btns_section(), 0)
def _create_btns_section(self):
btns_widget = QtWidgets.QWidget(self)
btns_layout = QtWidgets.QHBoxLayout(btns_widget)
btns_layout.setContentsMargins(0, 0, 0, 0)
copy_to_clipboard_btn = QtWidgets.QPushButton(
"Copy to clipboard", btns_widget
)
export_to_file_btn = QtWidgets.QPushButton(
"Export", btns_widget
)
btns_layout.addWidget(QtWidgets.QWidget(btns_widget), 1)
btns_layout.addWidget(copy_to_clipboard_btn)
btns_layout.addWidget(export_to_file_btn)
copy_to_clipboard_btn.clicked.connect(self._on_copy_to_clipboard)
export_to_file_btn.clicked.connect(self._on_export_to_file)
return btns_widget
def _on_export_to_file(self):
dst_dir_path = QtWidgets.QFileDialog.getExistingDirectory(
self,
"Choose directory",
os.path.expanduser("~"),
QtWidgets.QFileDialog.ShowDirsOnly
)
if not dst_dir_path or not os.path.exists(dst_dir_path):
return
filepath = extract_pype_info_to_file(dst_dir_path)
title = "Extraction done"
message = "Extraction is done. Destination filepath is \"{}\"".format(
filepath.replace("\\", "/")
)
dialog = QtWidgets.QMessageBox(self)
dialog.setIcon(QtWidgets.QMessageBox.NoIcon)
dialog.setWindowTitle(title)
dialog.setText(message)
dialog.exec_()
def _on_copy_to_clipboard(self):
all_data = get_all_current_info()
all_data_str = json.dumps(all_data, indent=4)
mime_data = QtCore.QMimeData()
mime_data.setText(all_data_str)
QtWidgets.QApplication.instance().clipboard().setMimeData(
mime_data
)
def _create_separator(self):
separator_widget = QtWidgets.QWidget(self)
separator_widget.setStyleSheet("background: #222222;")
separator_widget.setMinimumHeight(2)
separator_widget.setMaximumHeight(2)
return separator_widget
def _create_workstation_widget(self):
key_label_mapping = {
"system_name": "System:",
"local_id": "Local ID:",
"username": "Username:",
"hostname": "Hostname:",
"hostip": "Host IP:"
}
keys_order = [
"system_name",
"local_id",
"username",
"hostname",
"hostip"
]
workstation_info = get_workstation_info()
for key in workstation_info.keys():
if key not in keys_order:
keys_order.append(key)
wokstation_info_widget = CollapsibleWidget("Workstation info", self)
info_widget = QtWidgets.QWidget(self)
info_layout = QtWidgets.QGridLayout(info_widget)
# Add spacer to 3rd column
info_layout.addWidget(QtWidgets.QWidget(info_widget), 0, 2)
info_layout.setColumnStretch(2, 1)
for key in keys_order:
if key not in workstation_info:
continue
label = key_label_mapping.get(key, key)
value = workstation_info[key]
row = info_layout.rowCount()
info_layout.addWidget(
QtWidgets.QLabel(label), row, 0, 1, 1
)
value_label = QtWidgets.QLabel(value)
value_label.setTextInteractionFlags(
QtCore.Qt.TextSelectableByMouse
)
info_layout.addWidget(
value_label, row, 1, 1, 1
)
wokstation_info_widget.set_content_widget(info_widget)
return wokstation_info_widget
def _create_local_settings_widget(self):
local_settings = get_local_settings()
local_settings_widget = CollapsibleWidget("Local settings", self)
settings_input = QtWidgets.QPlainTextEdit(local_settings_widget)
settings_input.setReadOnly(True)
settings_input.setPlainText(json.dumps(local_settings, indent=4))
local_settings_widget.set_content_widget(settings_input)
return local_settings_widget
def _create_environ_widget(self):
env_widget = CollapsibleWidget("Environments", self)
env_view = EnvironmentsView(env_widget)
env_widget.set_content_widget(env_view)
return env_widget
def _create_pype_info_widget(self):
"""Create widget with information about pype application."""
# Get pype info data
pype_info = get_pype_info()
# Modify version key/values
version_value = "{} ({})".format(
pype_info.pop("version", self.not_applicable),
pype_info.pop("version_type", self.not_applicable)
)
pype_info["version_value"] = version_value
# Prepare lable mapping
key_label_mapping = {
"version_value": "Pype version:",
"executable": "Pype executable:",
"pype_root": "Pype location:",
"mongo_url": "Pype Mongo URL:"
}
# Prepare keys order
keys_order = ["version_value", "executable", "pype_root", "mongo_url"]
for key in pype_info.keys():
if key not in keys_order:
keys_order.append(key)
# Create widgets
info_widget = QtWidgets.QWidget(self)
info_layout = QtWidgets.QGridLayout(info_widget)
# Add spacer to 3rd column
info_layout.addWidget(QtWidgets.QWidget(info_widget), 0, 2)
info_layout.setColumnStretch(2, 1)
title_label = QtWidgets.QLabel(info_widget)
title_label.setText("Application information")
title_label.setStyleSheet("font-weight: bold;")
info_layout.addWidget(title_label, 0, 0, 1, 2)
for key in keys_order:
if key not in pype_info:
continue
value = pype_info[key]
label = key_label_mapping.get(key, key)
row = info_layout.rowCount()
info_layout.addWidget(
QtWidgets.QLabel(label), row, 0, 1, 1
)
value_label = QtWidgets.QLabel(value)
value_label.setTextInteractionFlags(
QtCore.Qt.TextSelectableByMouse
)
info_layout.addWidget(
value_label, row, 1, 1, 1
)
return info_widget

View file

@ -3,15 +3,12 @@ import sys
import platform
from avalon import style
from Qt import QtCore, QtGui, QtWidgets, QtSvg
from Qt import QtCore, QtGui, QtWidgets
from pype.api import Logger, resources
from pype.modules import TrayModulesManager, ITrayService
from pype.settings.lib import get_system_settings
import pype.version
try:
import configparser
except Exception:
import ConfigParser as configparser
from .pype_info_widget import PypeInfoWidget
class TrayManager:
@ -19,13 +16,14 @@ class TrayManager:
Load submenus, actions, separators and modules into tray's context.
"""
available_sourcetypes = ["python", "file"]
def __init__(self, tray_widget, main_window):
self.tray_widget = tray_widget
self.main_window = main_window
self.log = Logger().get_logger(self.__class__.__name__)
self.pype_info_widget = None
self.log = Logger.get_logger(self.__class__.__name__)
self.module_settings = get_system_settings()["modules"]
@ -36,7 +34,7 @@ class TrayManager:
def initialize_modules(self):
"""Add modules to tray."""
self.modules_manager.initialize(self.tray_widget.menu)
self.modules_manager.initialize(self, self.tray_widget.menu)
# Add services if they are
services_submenu = ITrayService.services_submenu(self.tray_widget.menu)
@ -58,6 +56,26 @@ class TrayManager:
# Print time report
self.modules_manager.print_report()
def show_tray_message(self, title, message, icon=None, msecs=None):
"""Show tray message.
Args:
title (str): Title of message.
message (str): Content of message.
icon (QSystemTrayIcon.MessageIcon): Message's icon. Default is
Information icon, may differ by Qt version.
msecs (int): Duration of message visibility in miliseconds.
Default is 10000 msecs, may differ by Qt version.
"""
args = [title, message]
kwargs = {}
if icon:
kwargs["icon"] = icon
if msecs:
kwargs["msecs"] = msecs
self.tray_widget.showMessage(*args, **kwargs)
def _add_version_item(self):
subversion = os.environ.get("PYPE_SUBVERSION")
client_name = os.environ.get("PYPE_CLIENT")
@ -70,12 +88,21 @@ class TrayManager:
version_string += ", {}".format(client_name)
version_action = QtWidgets.QAction(version_string, self.tray_widget)
version_action.triggered.connect(self._on_version_action)
self.tray_widget.menu.addAction(version_action)
self.tray_widget.menu.addSeparator()
def on_exit(self):
self.modules_manager.on_exit()
def _on_version_action(self):
if self.pype_info_widget is None:
self.pype_info_widget = PypeInfoWidget()
self.pype_info_widget.show()
self.pype_info_widget.raise_()
self.pype_info_widget.activateWindow()
class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
"""Tray widget.
@ -85,9 +112,9 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
"""
def __init__(self, parent):
self.icon = QtGui.QIcon(resources.pype_icon_filepath())
icon = QtGui.QIcon(resources.pype_icon_filepath())
QtWidgets.QSystemTrayIcon.__init__(self, self.icon, parent)
super(SystemTrayIcon, self).__init__(icon, parent)
# Store parent - QtWidgets.QMainWindow()
self.parent = parent
@ -100,15 +127,15 @@ class SystemTrayIcon(QtWidgets.QSystemTrayIcon):
self.tray_man = TrayManager(self, self.parent)
self.tray_man.initialize_modules()
# Catch activate event
self.activated.connect(self.on_systray_activated)
# Catch activate event for left click if not on MacOS
# - MacOS has this ability by design so menu would be doubled
if platform.system().lower() != "darwin":
self.activated.connect(self.on_systray_activated)
# Add menu to Context of SystemTrayIcon
self.setContextMenu(self.menu)
def on_systray_activated(self, reason):
# show contextMenu if left click
if platform.system().lower() == "darwin":
return
if reason == QtWidgets.QSystemTrayIcon.Trigger:
position = QtGui.QCursor().pos()
self.contextMenu().popup(position)
@ -128,119 +155,24 @@ class TrayMainWindow(QtWidgets.QMainWindow):
Every widget should have set this window as parent because
QSystemTrayIcon widget is not allowed to be a parent of any widget.
:param app: Qt application manages application's control flow
:type app: QtWidgets.QApplication
.. note::
*TrayMainWindow* has ability to show **working** widget.
Calling methods:
- ``show_working()``
- ``hide_working()``
.. todo:: Hide working widget if idle is too long
"""
def __init__(self, app):
super().__init__()
super(TrayMainWindow, self).__init__()
self.app = app
self.set_working_widget()
self.trayIcon = SystemTrayIcon(self)
self.trayIcon.show()
def set_working_widget(self):
image_file = resources.get_resource("icons", "working.svg")
img_pix = QtGui.QPixmap(image_file)
if image_file.endswith('.svg'):
widget = QtSvg.QSvgWidget(image_file)
else:
widget = QtWidgets.QLabel()
widget.setPixmap(img_pix)
# Set widget properties
widget.setGeometry(img_pix.rect())
widget.setMask(img_pix.mask())
widget.setWindowFlags(
QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.FramelessWindowHint
)
widget.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
self.center_widget(widget)
self._working_widget = widget
self.helper = DragAndDropHelper(self._working_widget)
def center_widget(self, widget):
frame_geo = widget.frameGeometry()
screen = self.app.desktop().cursor().pos()
center_point = self.app.desktop().screenGeometry(
self.app.desktop().screenNumber(screen)
).center()
frame_geo.moveCenter(center_point)
widget.move(frame_geo.topLeft())
def show_working(self):
self._working_widget.show()
def hide_working(self):
self.center_widget(self._working_widget)
self._working_widget.hide()
class DragAndDropHelper:
""" Helper adds to widget drag and drop ability
:param widget: Qt Widget where drag and drop ability will be added
"""
def __init__(self, widget):
self.widget = widget
self.widget.mousePressEvent = self.mousePressEvent
self.widget.mouseMoveEvent = self.mouseMoveEvent
self.widget.mouseReleaseEvent = self.mouseReleaseEvent
def mousePressEvent(self, event):
self.__mousePressPos = None
self.__mouseMovePos = None
if event.button() == QtCore.Qt.LeftButton:
self.__mousePressPos = event.globalPos()
self.__mouseMovePos = event.globalPos()
def mouseMoveEvent(self, event):
if event.buttons() == QtCore.Qt.LeftButton:
# adjust offset from clicked point to origin of widget
currPos = self.widget.mapToGlobal(
self.widget.pos()
)
globalPos = event.globalPos()
diff = globalPos - self.__mouseMovePos
newPos = self.widget.mapFromGlobal(currPos + diff)
self.widget.move(newPos)
self.__mouseMovePos = globalPos
def mouseReleaseEvent(self, event):
if self.__mousePressPos is not None:
moved = event.globalPos() - self.__mousePressPos
if moved.manhattanLength() > 3:
event.ignore()
return
self.tray_widget = SystemTrayIcon(self)
self.tray_widget.show()
class PypeTrayApplication(QtWidgets.QApplication):
"""Qt application manages application's control flow."""
def __init__(self):
super(self.__class__, self).__init__(sys.argv)
super(PypeTrayApplication, self).__init__(sys.argv)
# Allows to close widgets without exiting app
self.setQuitOnLastWindowClosed(False)
# Allow show icon istead of python icon in task bar (Windows)
if os.name == "nt":
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
u"pype_tray"
)
# Sets up splash
splash_widget = self.set_splash()