diff --git a/pype/hosts/maya/api/__init__.py b/pype/hosts/maya/api/__init__.py
index 27e15e0b25..ea100dda0f 100644
--- a/pype/hosts/maya/api/__init__.py
+++ b/pype/hosts/maya/api/__init__.py
@@ -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()
diff --git a/pype/hosts/maya/api/action.py b/pype/hosts/maya/api/action.py
index 35a57a4445..f623298451 100644
--- a/pype/hosts/maya/api/action.py
+++ b/pype/hosts/maya/api/action.py
@@ -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']
diff --git a/pype/hosts/maya/api/lib.py b/pype/hosts/maya/api/lib.py
index dc802b6a37..44f1577f7f 100644
--- a/pype/hosts/maya/api/lib.py
+++ b/pype/hosts/maya/api/lib.py
@@ -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
diff --git a/pype/hosts/maya/plugins/publish/extract_playblast.py b/pype/hosts/maya/plugins/publish/extract_playblast.py
index 770b077e41..99411e7f53 100644
--- a/pype/hosts/maya/plugins/publish/extract_playblast.py
+++ b/pype/hosts/maya/plugins/publish/extract_playblast.py
@@ -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)
diff --git a/pype/hosts/maya/plugins/publish/extract_thumbnail.py b/pype/hosts/maya/plugins/publish/extract_thumbnail.py
index 49511f6af6..9f6d16275f 100644
--- a/pype/hosts/maya/plugins/publish/extract_thumbnail.py
+++ b/pype/hosts/maya/plugins/publish/extract_thumbnail.py
@@ -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:
diff --git a/pype/hosts/nuke/plugins/load/load_mov.py b/pype/hosts/nuke/plugins/load/load_mov.py
index 435f26ad98..830359ccf9 100644
--- a/pype/hosts/nuke/plugins/load/load_mov.py
+++ b/pype/hosts/nuke/plugins/load/load_mov.py
@@ -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"]
diff --git a/pype/hosts/photoshop/plugins/create/create_image.py b/pype/hosts/photoshop/plugins/create/create_image.py
index 54b6efad29..03250acd48 100644
--- a/pype/hosts/photoshop/plugins/create/create_image.py
+++ b/pype/hosts/photoshop/plugins/create/create_image.py
@@ -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)
diff --git a/pype/hosts/photoshop/plugins/publish/collect_instances.py b/pype/hosts/photoshop/plugins/publish/collect_instances.py
index 14803cceee..5390df768b 100644
--- a/pype/hosts/photoshop/plugins/publish/collect_instances.py
+++ b/pype/hosts/photoshop/plugins/publish/collect_instances.py
@@ -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")
diff --git a/pype/hosts/photoshop/plugins/publish/validate_naming.py b/pype/hosts/photoshop/plugins/publish/validate_naming.py
index 2483adcb5e..48f5901233 100644
--- a/pype/hosts/photoshop/plugins/publish/validate_naming.py
+++ b/pype/hosts/photoshop/plugins/publish/validate_naming.py
@@ -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
diff --git a/pype/hosts/photoshop/plugins/publish/validate_unique_subsets.py b/pype/hosts/photoshop/plugins/publish/validate_unique_subsets.py
new file mode 100644
index 0000000000..5871f79668
--- /dev/null
+++ b/pype/hosts/photoshop/plugins/publish/validate_unique_subsets.py
@@ -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
diff --git a/pype/lib/pype_info.py b/pype/lib/pype_info.py
new file mode 100644
index 0000000000..cbcc5811a0
--- /dev/null
+++ b/pype/lib/pype_info.py
@@ -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
diff --git a/pype/modules/base.py b/pype/modules/base.py
index 7efd00e39e..03a5965841 100644
--- a/pype/modules/base.py
+++ b/pype/modules/base.py
@@ -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:
diff --git a/pype/resources/icons/working.svg b/pype/resources/icons/working.svg
deleted file mode 100644
index fe73f15a31..0000000000
--- a/pype/resources/icons/working.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
diff --git a/pype/settings/defaults/project_settings/maya.json b/pype/settings/defaults/project_settings/maya.json
index 03955732d2..75aa32fb36 100644
--- a/pype/settings/defaults/project_settings/maya.json
+++ b/pype/settings/defaults/project_settings/maya.json
@@ -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,
diff --git a/pype/settings/defaults/project_settings/nuke.json b/pype/settings/defaults/project_settings/nuke.json
index 517065f79a..5821584932 100644
--- a/pype/settings/defaults/project_settings/nuke.json
+++ b/pype/settings/defaults/project_settings/nuke.json
@@ -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": {
diff --git a/pype/settings/defaults/project_settings/standalonepublisher.json b/pype/settings/defaults/project_settings/standalonepublisher.json
index ad1b5e82b2..08895bcba9 100644
--- a/pype/settings/defaults/project_settings/standalonepublisher.json
+++ b/pype/settings/defaults/project_settings/standalonepublisher.json
@@ -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": []
+ }
+ }
}
}
\ No newline at end of file
diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_maya.json b/pype/settings/entities/schemas/projects_schema/schema_project_maya.json
index 7a270b0046..0a59cab510 100644
--- a/pype/settings/entities/schemas/projects_schema/schema_project_maya.json
+++ b/pype/settings/entities/schemas/projects_schema/schema_project_maya.json
@@ -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",
diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json b/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json
index 0548bd3544..220d56a306 100644
--- a/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json
+++ b/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json
@@ -45,6 +45,11 @@
"type": "schema",
"name": "schema_nuke_publish",
"template_data": []
+ },
+ {
+ "type": "schema",
+ "name": "schema_nuke_load",
+ "template_data": []
},
{
"type": "schema",
diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json
deleted file mode 100644
index 4745a19075..0000000000
--- a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json
+++ /dev/null
@@ -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": "Codec"
- },
- {
- "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": "Display Options"
- },
- {
- "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": "Generic"
- },
- {
- "type": "boolean",
- "key": "isolate_view",
- "label": " Isolate view"
- },
- {
- "type": "boolean",
- "key": "off_screen",
- "label": " Off Screen"
- }
- ]
- },
- {
- "type": "dict",
- "key": "IO",
- "children": [
- {
- "type": "label",
- "label": "IO"
- },
- {
- "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": "Renderer"
- },
- {
- "type": "text",
- "key": "rendererName",
- "label": " Renderer name"
- }
- ]
- },
- {
- "type": "dict",
- "key": "Resolution",
- "children": [
- {
- "type": "splitter"
- },
- {
- "type": "label",
- "label": "Resolution"
- },
- {
- "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": "Time Range"
- },
- {
- "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
- }
- ]
- }
- ]
-}
diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json
index 58a21c185a..6ecda224ea 100644
--- a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json
+++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json
@@ -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,
diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_nuke_load.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_nuke_load.json
new file mode 100644
index 0000000000..9d132e33b4
--- /dev/null
+++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_nuke_load.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/pype/settings/entities/schemas/projects_schema/schemas/template_maya_capture.json b/pype/settings/entities/schemas/projects_schema/schemas/template_maya_capture.json
new file mode 100644
index 0000000000..e4e0b034dd
--- /dev/null
+++ b/pype/settings/entities/schemas/projects_schema/schemas/template_maya_capture.json
@@ -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": "Codec"
+ },
+ {
+ "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": "Display Options"
+ },
+ {
+ "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": "Generic"
+ },
+ {
+ "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": "Renderer"
+ },
+ {
+ "type": "enum",
+ "key": "rendererName",
+ "label": "Renderer name",
+ "enum_items": [
+ { "vp2Renderer": "Viewport 2.0" }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "dict",
+ "key": "Resolution",
+ "children": [
+ {
+ "type": "splitter"
+ },
+ {
+ "type": "label",
+ "label": "Resolution"
+ },
+ {
+ "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
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/pype/tools/tray/pype_info_widget.py b/pype/tools/tray/pype_info_widget.py
new file mode 100644
index 0000000000..a4c52eb1d0
--- /dev/null
+++ b/pype/tools/tray/pype_info_widget.py
@@ -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
diff --git a/pype/tools/tray/pype_tray.py b/pype/tools/tray/pype_tray.py
index c27df16276..2d37c04136 100644
--- a/pype/tools/tray/pype_tray.py
+++ b/pype/tools/tray/pype_tray.py
@@ -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()