diff --git a/openpype/hosts/blender/api/plugin.py b/openpype/hosts/blender/api/plugin.py
index 50b73ade2b..6d437059b8 100644
--- a/openpype/hosts/blender/api/plugin.py
+++ b/openpype/hosts/blender/api/plugin.py
@@ -95,6 +95,30 @@ def get_local_collection_with_name(name):
return None
+def deselect_all():
+ """Deselect all objects in the scene.
+
+ Blender gives context error if trying to deselect object that it isn't
+ in object mode.
+ """
+ modes = []
+ active = bpy.context.view_layer.objects.active
+
+ for obj in bpy.data.objects:
+ if obj.mode != 'OBJECT':
+ modes.append((obj, obj.mode))
+ bpy.context.view_layer.objects.active = obj
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+ bpy.ops.object.select_all(action='DESELECT')
+
+ for p in modes:
+ bpy.context.view_layer.objects.active = p[0]
+ bpy.ops.object.mode_set(mode=p[1])
+
+ bpy.context.view_layer.objects.active = active
+
+
class Creator(PypeCreatorMixin, blender.Creator):
pass
diff --git a/openpype/hosts/blender/plugins/load/load_abc.py b/openpype/hosts/blender/plugins/load/load_abc.py
index 92656fac9e..5969432c36 100644
--- a/openpype/hosts/blender/plugins/load/load_abc.py
+++ b/openpype/hosts/blender/plugins/load/load_abc.py
@@ -47,7 +47,7 @@ class CacheModelLoader(plugin.AssetLoader):
bpy.data.objects.remove(empty)
def _process(self, libpath, asset_group, group_name):
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
collection = bpy.context.view_layer.active_layer_collection.collection
@@ -109,7 +109,7 @@ class CacheModelLoader(plugin.AssetLoader):
avalon_info = obj[AVALON_PROPERTY]
avalon_info.update({"container_name": group_name})
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
return objects
diff --git a/openpype/hosts/blender/plugins/load/load_fbx.py b/openpype/hosts/blender/plugins/load/load_fbx.py
index b80dc69adc..5f69aecb1a 100644
--- a/openpype/hosts/blender/plugins/load/load_fbx.py
+++ b/openpype/hosts/blender/plugins/load/load_fbx.py
@@ -46,7 +46,7 @@ class FbxModelLoader(plugin.AssetLoader):
bpy.data.objects.remove(obj)
def _process(self, libpath, asset_group, group_name, action):
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
collection = bpy.context.view_layer.active_layer_collection.collection
@@ -112,7 +112,7 @@ class FbxModelLoader(plugin.AssetLoader):
avalon_info = obj[AVALON_PROPERTY]
avalon_info.update({"container_name": group_name})
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
return objects
diff --git a/openpype/hosts/blender/plugins/load/load_layout_blend.py b/openpype/hosts/blender/plugins/load/load_layout_blend.py
index 85cb4dfbd3..4c1f751a77 100644
--- a/openpype/hosts/blender/plugins/load/load_layout_blend.py
+++ b/openpype/hosts/blender/plugins/load/load_layout_blend.py
@@ -150,7 +150,7 @@ class BlendLayoutLoader(plugin.AssetLoader):
bpy.data.orphans_purge(do_local_ids=False)
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
return objects
diff --git a/openpype/hosts/blender/plugins/load/load_layout_json.py b/openpype/hosts/blender/plugins/load/load_layout_json.py
index 1a4dbbb5cb..38718fd9b2 100644
--- a/openpype/hosts/blender/plugins/load/load_layout_json.py
+++ b/openpype/hosts/blender/plugins/load/load_layout_json.py
@@ -59,7 +59,7 @@ class JsonLayoutLoader(plugin.AssetLoader):
return None
def _process(self, libpath, asset, asset_group, actions):
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
with open(libpath, "r") as fp:
data = json.load(fp)
diff --git a/openpype/hosts/blender/plugins/load/load_model.py b/openpype/hosts/blender/plugins/load/load_model.py
index af5591c299..c33c656dec 100644
--- a/openpype/hosts/blender/plugins/load/load_model.py
+++ b/openpype/hosts/blender/plugins/load/load_model.py
@@ -93,7 +93,7 @@ class BlendModelLoader(plugin.AssetLoader):
bpy.data.orphans_purge(do_local_ids=False)
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
return objects
@@ -126,7 +126,7 @@ class BlendModelLoader(plugin.AssetLoader):
asset_group.empty_display_type = 'SINGLE_ARROW'
avalon_container.objects.link(asset_group)
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
if options is not None:
parent = options.get('parent')
@@ -158,7 +158,7 @@ class BlendModelLoader(plugin.AssetLoader):
bpy.ops.object.parent_set(keep_transform=True)
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
objects = self._process(libpath, asset_group, group_name)
diff --git a/openpype/hosts/blender/plugins/load/load_rig.py b/openpype/hosts/blender/plugins/load/load_rig.py
index 6062c293df..e80da8af45 100644
--- a/openpype/hosts/blender/plugins/load/load_rig.py
+++ b/openpype/hosts/blender/plugins/load/load_rig.py
@@ -156,7 +156,7 @@ class BlendRigLoader(plugin.AssetLoader):
while bpy.data.orphans_purge(do_local_ids=False):
pass
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
return objects
@@ -191,7 +191,7 @@ class BlendRigLoader(plugin.AssetLoader):
action = None
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
create_animation = False
@@ -227,7 +227,7 @@ class BlendRigLoader(plugin.AssetLoader):
bpy.ops.object.parent_set(keep_transform=True)
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
objects = self._process(libpath, asset_group, group_name, action)
@@ -250,7 +250,7 @@ class BlendRigLoader(plugin.AssetLoader):
data={"dependencies": str(context["representation"]["_id"])}
)
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
bpy.context.scene.collection.objects.link(asset_group)
diff --git a/openpype/hosts/blender/plugins/publish/extract_abc.py b/openpype/hosts/blender/plugins/publish/extract_abc.py
index 4696da3db4..b75bec4e28 100644
--- a/openpype/hosts/blender/plugins/publish/extract_abc.py
+++ b/openpype/hosts/blender/plugins/publish/extract_abc.py
@@ -28,7 +28,7 @@ class ExtractABC(api.Extractor):
# Perform extraction
self.log.info("Performing extraction..")
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
selected = []
asset_group = None
@@ -50,7 +50,7 @@ class ExtractABC(api.Extractor):
flatten=False
)
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
if "representations" not in instance.data:
instance.data["representations"] = []
diff --git a/openpype/hosts/blender/plugins/publish/extract_fbx.py b/openpype/hosts/blender/plugins/publish/extract_fbx.py
index b91f2a75ef..f9ffdea1d1 100644
--- a/openpype/hosts/blender/plugins/publish/extract_fbx.py
+++ b/openpype/hosts/blender/plugins/publish/extract_fbx.py
@@ -24,7 +24,7 @@ class ExtractFBX(api.Extractor):
# Perform extraction
self.log.info("Performing extraction..")
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
selected = []
asset_group = None
@@ -60,7 +60,7 @@ class ExtractFBX(api.Extractor):
add_leaf_bones=False
)
- bpy.ops.object.select_all(action='DESELECT')
+ plugin.deselect_all()
for mat in new_materials:
bpy.data.materials.remove(mat)
diff --git a/openpype/hosts/celaction/api/cli.py b/openpype/hosts/celaction/api/cli.py
index acd9da8229..bc1e3eaf89 100644
--- a/openpype/hosts/celaction/api/cli.py
+++ b/openpype/hosts/celaction/api/cli.py
@@ -4,7 +4,6 @@ import copy
import argparse
from avalon import io
-from avalon.tools import publish
import pyblish.api
import pyblish.util
@@ -13,6 +12,7 @@ from openpype.api import Logger
import openpype
import openpype.hosts.celaction
from openpype.hosts.celaction import api as celaction
+from openpype.tools.utils import host_tools
log = Logger().get_logger("Celaction_cli_publisher")
@@ -82,7 +82,7 @@ def main():
pyblish.api.register_host(publish_host)
- return publish.show()
+ return host_tools.show_publish()
if __name__ == "__main__":
diff --git a/openpype/hosts/fusion/api/__init__.py b/openpype/hosts/fusion/api/__init__.py
index 5581a0a9cb..5aee978c15 100644
--- a/openpype/hosts/fusion/api/__init__.py
+++ b/openpype/hosts/fusion/api/__init__.py
@@ -1,8 +1,6 @@
from .pipeline import (
install,
- uninstall,
- publish,
- launch_workfiles_app
+ uninstall
)
from .utils import (
@@ -22,12 +20,9 @@ __all__ = [
# pipeline
"install",
"uninstall",
- "publish",
- "launch_workfiles_app",
# utils
"setup",
- "get_resolve_module",
# lib
"get_additional_data",
diff --git a/openpype/hosts/fusion/api/menu.py b/openpype/hosts/fusion/api/menu.py
index 9093aa9e5e..5d2efb4911 100644
--- a/openpype/hosts/fusion/api/menu.py
+++ b/openpype/hosts/fusion/api/menu.py
@@ -3,19 +3,7 @@ import sys
from Qt import QtWidgets, QtCore
-from .pipeline import (
- publish,
- launch_workfiles_app
-)
-
-from avalon.tools import (
- creator,
- sceneinventory,
-)
-from openpype.tools import (
- loader,
- libraryloader
-)
+from openpype.tools.utils import host_tools
from openpype.hosts.fusion.scripts import (
set_rendermode,
@@ -36,7 +24,7 @@ def load_stylesheet():
class Spacer(QtWidgets.QWidget):
def __init__(self, height, *args, **kwargs):
- super(self.__class__, self).__init__(*args, **kwargs)
+ super(Spacer, self).__init__(*args, **kwargs)
self.setFixedHeight(height)
@@ -53,7 +41,7 @@ class Spacer(QtWidgets.QWidget):
class OpenPypeMenu(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
- super(self.__class__, self).__init__(*args, **kwargs)
+ super(OpenPypeMenu, self).__init__(*args, **kwargs)
self.setObjectName("OpenPypeMenu")
@@ -117,27 +105,27 @@ class OpenPypeMenu(QtWidgets.QWidget):
def on_workfile_clicked(self):
print("Clicked Workfile")
- launch_workfiles_app()
+ host_tools.show_workfiles()
def on_create_clicked(self):
print("Clicked Create")
- creator.show()
+ host_tools.show_creator()
def on_publish_clicked(self):
print("Clicked Publish")
- publish(None)
+ host_tools.show_publish()
def on_load_clicked(self):
print("Clicked Load")
- loader.show(use_context=True)
+ host_tools.show_loader(use_context=True)
def on_inventory_clicked(self):
print("Clicked Inventory")
- sceneinventory.show()
+ host_tools.show_scene_inventory()
def on_libload_clicked(self):
print("Clicked Library")
- libraryloader.show()
+ host_tools.show_library_loader()
def on_rendernode_clicked(self):
from avalon import style
diff --git a/openpype/hosts/fusion/api/pipeline.py b/openpype/hosts/fusion/api/pipeline.py
index 688e75f6fe..c721146830 100644
--- a/openpype/hosts/fusion/api/pipeline.py
+++ b/openpype/hosts/fusion/api/pipeline.py
@@ -3,7 +3,6 @@ Basic avalon integration
"""
import os
-from openpype.tools import workfiles
from avalon import api as avalon
from pyblish import api as pyblish
from openpype.api import Logger
@@ -98,14 +97,3 @@ def on_pyblish_instance_toggled(instance, new_value, old_value):
current = attrs["TOOLB_PassThrough"]
if current != passthrough:
tool.SetAttrs({"TOOLB_PassThrough": passthrough})
-
-
-def launch_workfiles_app(*args):
- workdir = os.environ["AVALON_WORKDIR"]
- workfiles.show(workdir)
-
-
-def publish(parent):
- """Shorthand to publish from within host"""
- from avalon.tools import publish
- return publish.show(parent)
diff --git a/openpype/hosts/harmony/api/__init__.py b/openpype/hosts/harmony/api/__init__.py
index fd21725bd5..bcf7dffbe7 100644
--- a/openpype/hosts/harmony/api/__init__.py
+++ b/openpype/hosts/harmony/api/__init__.py
@@ -3,17 +3,14 @@
import os
from pathlib import Path
import logging
-import re
from openpype import lib
-from openpype.api import (get_current_project_settings)
import openpype.hosts.harmony
import pyblish.api
from avalon import io, harmony
import avalon.api
-import avalon.tools.sceneinventory
log = logging.getLogger("openpype.hosts.harmony")
diff --git a/openpype/hosts/hiero/api/menu.py b/openpype/hosts/hiero/api/menu.py
index bcd78aa5bb..e3de220777 100644
--- a/openpype/hosts/hiero/api/menu.py
+++ b/openpype/hosts/hiero/api/menu.py
@@ -2,6 +2,7 @@ import os
import sys
import hiero.core
from openpype.api import Logger
+from openpype.tools.utils import host_tools
from avalon.api import Session
from hiero.ui import findMenuAction
@@ -41,8 +42,6 @@ def menu_install():
apply_colorspace_project, apply_colorspace_clips
)
# here is the best place to add menu
- from avalon.tools import creator, sceneinventory
- from openpype.tools import loader
from avalon.vendor.Qt import QtGui
menu_name = os.environ['AVALON_LABEL']
@@ -87,15 +86,15 @@ def menu_install():
creator_action = menu.addAction("Create ...")
creator_action.setIcon(QtGui.QIcon("icons:CopyRectangle.png"))
- creator_action.triggered.connect(creator.show)
+ creator_action.triggered.connect(host_tools.show_creator)
loader_action = menu.addAction("Load ...")
loader_action.setIcon(QtGui.QIcon("icons:CopyRectangle.png"))
- loader_action.triggered.connect(loader.show)
+ loader_action.triggered.connect(host_tools.show_loader)
sceneinventory_action = menu.addAction("Manage ...")
sceneinventory_action.setIcon(QtGui.QIcon("icons:CopyRectangle.png"))
- sceneinventory_action.triggered.connect(sceneinventory.show)
+ sceneinventory_action.triggered.connect(host_tools.show_scene_inventory)
menu.addSeparator()
if os.getenv("OPENPYPE_DEVELOP"):
diff --git a/openpype/hosts/hiero/api/pipeline.py b/openpype/hosts/hiero/api/pipeline.py
index 12f6923de7..6f6588e1be 100644
--- a/openpype/hosts/hiero/api/pipeline.py
+++ b/openpype/hosts/hiero/api/pipeline.py
@@ -4,13 +4,12 @@ Basic avalon integration
import os
import contextlib
from collections import OrderedDict
-from avalon.tools import publish as _publish
-from openpype.tools import workfiles
from avalon.pipeline import AVALON_CONTAINER_ID
from avalon import api as avalon
from avalon import schema
from pyblish import api as pyblish
from openpype.api import Logger
+from openpype.tools.utils import host_tools
from . import lib, menu, events
log = Logger().get_logger(__name__)
@@ -211,15 +210,13 @@ def update_container(track_item, data=None):
def launch_workfiles_app(*args):
''' Wrapping function for workfiles launcher '''
- workdir = os.environ["AVALON_WORKDIR"]
-
# show workfile gui
- workfiles.show(workdir)
+ host_tools.show_workfiles()
def publish(parent):
"""Shorthand to publish from within host"""
- return _publish.show(parent)
+ return host_tools.show_publish(parent)
@contextlib.contextmanager
diff --git a/openpype/hosts/houdini/startup/MainMenuCommon.xml b/openpype/hosts/houdini/startup/MainMenuCommon.xml
index 76585085e2..2b556a2e75 100644
--- a/openpype/hosts/houdini/startup/MainMenuCommon.xml
+++ b/openpype/hosts/houdini/startup/MainMenuCommon.xml
@@ -7,24 +7,30 @@
@@ -32,9 +38,9 @@ cbsceneinventory.show()
@@ -43,9 +49,10 @@ publish.show(parent)
diff --git a/openpype/hosts/maya/api/__init__.py b/openpype/hosts/maya/api/__init__.py
index 13f8a4cb78..d1c13b04d5 100644
--- a/openpype/hosts/maya/api/__init__.py
+++ b/openpype/hosts/maya/api/__init__.py
@@ -8,7 +8,7 @@ from avalon import api as avalon
from avalon import pipeline
from avalon.maya import suspended_refresh
from avalon.maya.pipeline import IS_HEADLESS
-from openpype.tools import workfiles
+from openpype.tools.utils import host_tools
from pyblish import api as pyblish
from openpype.lib import any_outdated
import openpype.hosts.maya
@@ -208,16 +208,12 @@ def on_init(_):
launch_workfiles = os.environ.get("WORKFILES_STARTUP")
if launch_workfiles:
- safe_deferred(launch_workfiles_app)
+ safe_deferred(host_tools.show_workfiles)
if not IS_HEADLESS:
safe_deferred(override_toolbox_ui)
-def launch_workfiles_app():
- workfiles.show(os.environ["AVALON_WORKDIR"])
-
-
def on_before_save(return_code, _):
"""Run validation for scene's FPS prior to saving"""
return lib.validate_fps()
diff --git a/openpype/hosts/maya/api/customize.py b/openpype/hosts/maya/api/customize.py
index a84412963b..8474262626 100644
--- a/openpype/hosts/maya/api/customize.py
+++ b/openpype/hosts/maya/api/customize.py
@@ -1,10 +1,16 @@
"""A set of commands that install overrides to Maya's UI"""
+import os
+import logging
+
+from functools import partial
+
import maya.cmds as mc
import maya.mel as mel
-from functools import partial
-import os
-import logging
+
+from avalon.maya import pipeline
+from openpype.api import resources
+from openpype.tools.utils import host_tools
log = logging.getLogger(__name__)
@@ -69,39 +75,8 @@ def override_component_mask_commands():
def override_toolbox_ui():
"""Add custom buttons in Toolbox as replacement for Maya web help icon."""
- inventory = None
- loader = None
- launch_workfiles_app = None
- mayalookassigner = None
- try:
- import avalon.tools.sceneinventory as inventory
- except Exception:
- log.warning("Could not import SceneInventory tool")
-
- try:
- import openpype.tools.loader as loader
- except Exception:
- log.warning("Could not import Loader tool")
-
- try:
- from avalon.maya.pipeline import launch_workfiles_app
- except Exception:
- log.warning("Could not import Workfiles tool")
-
- try:
- from openpype.tools import mayalookassigner
- except Exception:
- log.warning("Could not import Maya Look assigner tool")
-
- from openpype.api import resources
-
icons = resources.get_resource("icons")
- if not any((
- mayalookassigner, launch_workfiles_app, loader, inventory
- )):
- return
-
# Ensure the maya web icon on toolbox exists
web_button = "ToolBox|MainToolboxLayout|mayaWebButton"
if not mc.iconTextButton(web_button, query=True, exists=True):
@@ -120,14 +95,23 @@ def override_toolbox_ui():
# Create our controls
background_color = (0.267, 0.267, 0.267)
controls = []
- if mayalookassigner:
+ look_assigner = None
+ try:
+ look_assigner = host_tools.get_tool_by_name(
+ "lookassigner",
+ parent=pipeline._parent
+ )
+ except Exception:
+ log.warning("Couldn't create Look assigner window.", exc_info=True)
+
+ if look_assigner is not None:
controls.append(
mc.iconTextButton(
"pype_toolbox_lookmanager",
annotation="Look Manager",
label="Look Manager",
image=os.path.join(icons, "lookmanager.png"),
- command=lambda: mayalookassigner.show(),
+ command=host_tools.show_look_assigner,
bgc=background_color,
width=icon_size,
height=icon_size,
@@ -135,50 +119,53 @@ def override_toolbox_ui():
)
)
- if launch_workfiles_app:
- controls.append(
- mc.iconTextButton(
- "pype_toolbox_workfiles",
- annotation="Work Files",
- label="Work Files",
- image=os.path.join(icons, "workfiles.png"),
- command=lambda: launch_workfiles_app(),
- bgc=background_color,
- width=icon_size,
- height=icon_size,
- parent=parent
- )
+ controls.append(
+ mc.iconTextButton(
+ "pype_toolbox_workfiles",
+ annotation="Work Files",
+ label="Work Files",
+ image=os.path.join(icons, "workfiles.png"),
+ command=lambda: host_tools.show_workfiles(
+ parent=pipeline._parent
+ ),
+ bgc=background_color,
+ width=icon_size,
+ height=icon_size,
+ parent=parent
)
+ )
- if loader:
- controls.append(
- mc.iconTextButton(
- "pype_toolbox_loader",
- annotation="Loader",
- label="Loader",
- image=os.path.join(icons, "loader.png"),
- command=lambda: loader.show(use_context=True),
- bgc=background_color,
- width=icon_size,
- height=icon_size,
- parent=parent
- )
+ controls.append(
+ mc.iconTextButton(
+ "pype_toolbox_loader",
+ annotation="Loader",
+ label="Loader",
+ image=os.path.join(icons, "loader.png"),
+ command=lambda: host_tools.show_loader(
+ parent=pipeline._parent, use_context=True
+ ),
+ bgc=background_color,
+ width=icon_size,
+ height=icon_size,
+ parent=parent
)
+ )
- if inventory:
- controls.append(
- mc.iconTextButton(
- "pype_toolbox_manager",
- annotation="Inventory",
- label="Inventory",
- image=os.path.join(icons, "inventory.png"),
- command=lambda: inventory.show(),
- bgc=background_color,
- width=icon_size,
- height=icon_size,
- parent=parent
- )
+ controls.append(
+ mc.iconTextButton(
+ "pype_toolbox_manager",
+ annotation="Inventory",
+ label="Inventory",
+ image=os.path.join(icons, "inventory.png"),
+ command=lambda: host_tools.show_scene_inventory(
+ parent=pipeline._parent
+ ),
+ bgc=background_color,
+ width=icon_size,
+ height=icon_size,
+ parent=parent
)
+ )
# Add the buttons on the bottom and stack
# them above each other with side padding
diff --git a/openpype/hosts/maya/api/menu.py b/openpype/hosts/maya/api/menu.py
index ad225dcd28..4e69e41dca 100644
--- a/openpype/hosts/maya/api/menu.py
+++ b/openpype/hosts/maya/api/menu.py
@@ -2,13 +2,15 @@ import sys
import os
import logging
-from avalon.vendor.Qt import QtWidgets, QtGui
-from avalon.maya import pipeline
-from openpype.api import BuildWorkfile
-import maya.cmds as cmds
-from openpype.settings import get_project_settings
+from Qt import QtWidgets, QtGui
-self = sys.modules[__name__]
+import maya.cmds as cmds
+
+from avalon.maya import pipeline
+
+from openpype.api import BuildWorkfile
+from openpype.settings import get_project_settings
+from openpype.tools.utils import host_tools
log = logging.getLogger(__name__)
@@ -19,10 +21,8 @@ def _get_menu(menu_name=None):
if menu_name is None:
menu_name = pipeline._menu
- widgets = dict((
- w.objectName(), w) for w in QtWidgets.QApplication.allWidgets())
- menu = widgets.get(menu_name)
- return menu
+ widgets = {w.objectName(): w for w in QtWidgets.QApplication.allWidgets()}
+ return widgets.get(menu_name)
def deferred():
@@ -36,25 +36,52 @@ def deferred():
)
def add_look_assigner_item():
- import mayalookassigner
cmds.menuItem(
"Look assigner",
parent=pipeline._menu,
- command=lambda *args: mayalookassigner.show()
+ command=lambda *args: host_tools.show_look_assigner(
+ pipeline._parent
+ )
)
- def modify_workfiles():
- from openpype.tools import workfiles
-
- def launch_workfiles_app(*_args, **_kwargs):
- workfiles.show(
- os.path.join(
- cmds.workspace(query=True, rootDirectory=True),
- cmds.workspace(fileRuleEntry="scene")
- ),
- parent=pipeline._parent
+ def add_experimental_item():
+ cmds.menuItem(
+ "Experimental tools...",
+ parent=pipeline._menu,
+ command=lambda *args: host_tools.show_experimental_tools_dialog(
+ pipeline._parent
)
+ )
+ def add_scripts_menu():
+ try:
+ import scriptsmenu.launchformaya as launchformaya
+ except ImportError:
+ log.warning(
+ "Skipping studio.menu install, because "
+ "'scriptsmenu' module seems unavailable."
+ )
+ return
+
+ # load configuration of custom menu
+ project_settings = get_project_settings(os.getenv("AVALON_PROJECT"))
+ config = project_settings["maya"]["scriptsmenu"]["definition"]
+ _menu = project_settings["maya"]["scriptsmenu"]["name"]
+
+ if not config:
+ log.warning("Skipping studio menu, no definition found.")
+ return
+
+ # run the launcher for Maya menu
+ studio_menu = launchformaya.main(
+ title=_menu.title(),
+ objectName=_menu.title().lower().replace(" ", "_")
+ )
+
+ # apply configuration
+ studio_menu.build_from_configuration(studio_menu, config)
+
+ def modify_workfiles():
# Find the pipeline menu
top_menu = _get_menu()
@@ -75,7 +102,7 @@ def deferred():
cmds.menuItem(
"Work Files",
parent=pipeline._menu,
- command=launch_workfiles_app,
+ command=lambda *args: host_tools.show_workfiles(pipeline._parent),
insertAfter=after_action
)
@@ -109,38 +136,13 @@ def deferred():
log.info("Attempting to install scripts menu ...")
+ # add_scripts_menu()
add_build_workfiles_item()
add_look_assigner_item()
+ add_experimental_item()
modify_workfiles()
remove_project_manager()
-
- try:
- import scriptsmenu.launchformaya as launchformaya
- import scriptsmenu.scriptsmenu as scriptsmenu
- except ImportError:
- log.warning(
- "Skipping studio.menu install, because "
- "'scriptsmenu' module seems unavailable."
- )
- return
-
- # load configuration of custom menu
- project_settings = get_project_settings(os.getenv("AVALON_PROJECT"))
- config = project_settings["maya"]["scriptsmenu"]["definition"]
- _menu = project_settings["maya"]["scriptsmenu"]["name"]
-
- if not config:
- log.warning("Skipping studio menu, no definition found.")
- return
-
- # run the launcher for Maya menu
- studio_menu = launchformaya.main(
- title=_menu.title(),
- objectName=_menu.title().lower().replace(" ", "_")
- )
-
- # apply configuration
- studio_menu.build_from_configuration(studio_menu, config)
+ add_scripts_menu()
def uninstall():
@@ -161,7 +163,7 @@ def install():
return
# Allow time for uninstallation to finish.
- cmds.evalDeferred(deferred)
+ cmds.evalDeferred(deferred, lowestPriority=True)
def popup():
diff --git a/openpype/hosts/maya/plugins/publish/collect_render.py b/openpype/hosts/maya/plugins/publish/collect_render.py
index 575cc2456b..d2f277329a 100644
--- a/openpype/hosts/maya/plugins/publish/collect_render.py
+++ b/openpype/hosts/maya/plugins/publish/collect_render.py
@@ -244,17 +244,17 @@ class CollectMayaRender(pyblish.api.ContextPlugin):
# metadata file will be located in top-most common
# directory.
# TODO: use `os.path.commonpath()` after switch to Python 3
+ publish_meta_path = os.path.normpath(publish_meta_path)
common_publish_meta_path = os.path.splitdrive(
publish_meta_path)[0]
if common_publish_meta_path:
common_publish_meta_path += os.path.sep
- for part in publish_meta_path.split("/"):
+ for part in publish_meta_path.replace(
+ common_publish_meta_path, "").split(os.path.sep):
common_publish_meta_path = os.path.join(
common_publish_meta_path, part)
if part == expected_layer_name:
break
- common_publish_meta_path = common_publish_meta_path.replace(
- "\\", "/")
self.log.info(
"Publish meta path: {}".format(common_publish_meta_path))
diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py
index f112ba8255..9ee3a4464b 100644
--- a/openpype/hosts/nuke/api/lib.py
+++ b/openpype/hosts/nuke/api/lib.py
@@ -7,7 +7,6 @@ from collections import OrderedDict
from avalon import api, io, lib
-from openpype.tools import workfiles
import avalon.nuke
from avalon.nuke import lib as anlib
from avalon.nuke import (
@@ -24,7 +23,7 @@ from openpype.api import (
get_current_project_settings,
ApplicationManager
)
-
+from openpype.tools.utils import host_tools
import nuke
from .utils import set_context_favorites
@@ -1662,7 +1661,7 @@ def launch_workfiles_app():
if not opnl.workfiles_launched:
opnl.workfiles_launched = True
- workfiles.show(os.environ["AVALON_WORKDIR"])
+ host_tools.show_workfiles()
def process_workfile_builder():
diff --git a/openpype/hosts/nuke/api/menu.py b/openpype/hosts/nuke/api/menu.py
index 021ea04159..3e74893589 100644
--- a/openpype/hosts/nuke/api/menu.py
+++ b/openpype/hosts/nuke/api/menu.py
@@ -4,7 +4,7 @@ from avalon.api import Session
from .lib import WorkfileSettings
from openpype.api import Logger, BuildWorkfile, get_current_project_settings
-from openpype.tools import workfiles
+from openpype.tools.utils import host_tools
log = Logger().get_logger(__name__)
@@ -25,7 +25,7 @@ def install():
menu.removeItem(rm_item[1].name())
menu.addCommand(
name,
- workfiles.show,
+ host_tools.show_workfiles,
index=2
)
menu.addSeparator(index=3)
@@ -84,6 +84,12 @@ def install():
)
log.debug("Adding menu item: {}".format(name))
+ # Add experimental tools action
+ menu.addSeparator()
+ menu.addCommand(
+ "Experimental tools...",
+ host_tools.show_experimental_tools_dialog
+ )
# adding shortcuts
add_shortcuts_from_presets()
diff --git a/openpype/hosts/resolve/api/menu.py b/openpype/hosts/resolve/api/menu.py
index c639fd2db8..262ce739dd 100644
--- a/openpype/hosts/resolve/api/menu.py
+++ b/openpype/hosts/resolve/api/menu.py
@@ -8,15 +8,7 @@ from .pipeline import (
launch_workfiles_app
)
-from avalon.tools import (
- creator,
- sceneinventory,
- subsetmanager
-)
-from openpype.tools import (
- loader,
- libraryloader,
-)
+from openpype.tools.utils import host_tools
def load_stylesheet():
@@ -32,7 +24,7 @@ def load_stylesheet():
class Spacer(QtWidgets.QWidget):
def __init__(self, height, *args, **kwargs):
- super(self.__class__, self).__init__(*args, **kwargs)
+ super(Spacer, self).__init__(*args, **kwargs)
self.setFixedHeight(height)
@@ -49,7 +41,7 @@ class Spacer(QtWidgets.QWidget):
class OpenPypeMenu(QtWidgets.QWidget):
def __init__(self, *args, **kwargs):
- super(self.__class__, self).__init__(*args, **kwargs)
+ super(OpenPypeMenu, self).__init__(*args, **kwargs)
self.setObjectName("OpenPypeMenu")
@@ -119,7 +111,7 @@ class OpenPypeMenu(QtWidgets.QWidget):
def on_create_clicked(self):
print("Clicked Create")
- creator.show()
+ host_tools.show_creator()
def on_publish_clicked(self):
print("Clicked Publish")
@@ -127,19 +119,19 @@ class OpenPypeMenu(QtWidgets.QWidget):
def on_load_clicked(self):
print("Clicked Load")
- loader.show(use_context=True)
+ host_tools.show_loader(use_context=True)
def on_inventory_clicked(self):
print("Clicked Inventory")
- sceneinventory.show()
+ host_tools.show_scene_inventory()
def on_subsetm_clicked(self):
print("Clicked Subset Manager")
- subsetmanager.show()
+ host_tools.show_subset_manager()
def on_libload_clicked(self):
print("Clicked Library")
- libraryloader.show()
+ host_tools.show_library_loader()
def on_rename_clicked(self):
print("Clicked Rename")
diff --git a/openpype/hosts/resolve/api/pipeline.py b/openpype/hosts/resolve/api/pipeline.py
index 80249310e8..ce95cfe02a 100644
--- a/openpype/hosts/resolve/api/pipeline.py
+++ b/openpype/hosts/resolve/api/pipeline.py
@@ -4,7 +4,6 @@ Basic avalon integration
import os
import contextlib
from collections import OrderedDict
-from openpype.tools import workfiles
from avalon import api as avalon
from avalon import schema
from avalon.pipeline import AVALON_CONTAINER_ID
@@ -12,6 +11,7 @@ from pyblish import api as pyblish
from openpype.api import Logger
from . import lib
from . import PLUGINS_DIR
+from openpype.tools.utils import host_tools
log = Logger().get_logger(__name__)
PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish")
@@ -212,14 +212,12 @@ def update_container(timeline_item, data=None):
def launch_workfiles_app(*args):
- workdir = os.environ["AVALON_WORKDIR"]
- workfiles.show(workdir)
+ host_tools.show_workfiles()
def publish(parent):
"""Shorthand to publish from within host"""
- from avalon.tools import publish
- return publish.show(parent)
+ return host_tools.show_publish()
@contextlib.contextmanager
diff --git a/openpype/hosts/standalonepublisher/plugins/publish/validate_sources.py b/openpype/hosts/standalonepublisher/plugins/publish/validate_sources.py
new file mode 100644
index 0000000000..da424cfb45
--- /dev/null
+++ b/openpype/hosts/standalonepublisher/plugins/publish/validate_sources.py
@@ -0,0 +1,37 @@
+import pyblish.api
+import openpype.api
+
+import os
+
+
+class ValidateSources(pyblish.api.InstancePlugin):
+ """Validates source files.
+
+ Loops through all 'files' in 'stagingDir' if actually exist. They might
+ got deleted between starting of SP and now.
+
+ """
+
+ order = openpype.api.ValidateContentsOrder
+ label = "Check source files"
+
+ optional = True # only for unforeseeable cases
+
+ hosts = ["standalonepublisher"]
+
+ def process(self, instance):
+ self.log.info("instance {}".format(instance.data))
+
+ for repr in instance.data["representations"]:
+ files = []
+ if isinstance(repr["files"], str):
+ files.append(repr["files"])
+ else:
+ files = list(repr["files"])
+
+ for file_name in files:
+ source_file = os.path.join(repr["stagingDir"],
+ file_name)
+
+ if not os.path.exists(source_file):
+ raise ValueError("File {} not found".format(source_file))
diff --git a/openpype/modules/default_modules/avalon_apps/avalon_app.py b/openpype/modules/default_modules/avalon_apps/avalon_app.py
index d21b37e520..9e650a097e 100644
--- a/openpype/modules/default_modules/avalon_apps/avalon_app.py
+++ b/openpype/modules/default_modules/avalon_apps/avalon_app.py
@@ -1,6 +1,5 @@
import os
import openpype
-from openpype import resources
from openpype.modules import OpenPypeModule
from openpype_interfaces import ITrayModule
@@ -52,16 +51,12 @@ class AvalonModule(OpenPypeModule, ITrayModule):
def tray_init(self):
# Add library tool
try:
- from Qt import QtGui
- from avalon import style
from openpype.tools.libraryloader import LibraryLoaderWindow
self.libraryloader = LibraryLoaderWindow(
- icon=QtGui.QIcon(resources.get_openpype_icon_filepath()),
show_projects=True,
show_libraries=True
)
- self.libraryloader.setStyleSheet(style.load_stylesheet())
except Exception:
self.log.warning(
"Couldn't load Library loader tool for tray.",
@@ -70,6 +65,9 @@ class AvalonModule(OpenPypeModule, ITrayModule):
# Definition of Tray menu
def tray_menu(self, tray_menu):
+ if self.libraryloader is None:
+ return
+
from Qt import QtWidgets
# Actions
action_library_loader = QtWidgets.QAction(
@@ -87,6 +85,9 @@ class AvalonModule(OpenPypeModule, ITrayModule):
return
def show_library_loader(self):
+ if self.libraryloader is None:
+ return
+
self.libraryloader.show()
# Raise and activate the window
diff --git a/openpype/modules/default_modules/ftrack/event_handlers_server/action_prepare_project.py b/openpype/modules/default_modules/ftrack/event_handlers_server/action_prepare_project.py
index 85317031b2..2e55be2743 100644
--- a/openpype/modules/default_modules/ftrack/event_handlers_server/action_prepare_project.py
+++ b/openpype/modules/default_modules/ftrack/event_handlers_server/action_prepare_project.py
@@ -3,6 +3,7 @@ import json
from avalon.api import AvalonMongoDB
from openpype.api import ProjectSettings
from openpype.lib import create_project
+from openpype.settings import SaveWarningExc
from openpype_modules.ftrack.lib import (
ServerAction,
@@ -312,7 +313,6 @@ class PrepareProjectServer(ServerAction):
if not in_data:
return
-
root_values = {}
root_key = "__root__"
for key in tuple(in_data.keys()):
@@ -392,7 +392,12 @@ class PrepareProjectServer(ServerAction):
else:
attributes_entity[key] = value
- project_settings.save()
+ try:
+ project_settings.save()
+ except SaveWarningExc as exc:
+ self.log.info("Few warnings happened during settings save:")
+ for warning in exc.warnings:
+ self.log.info(str(warning))
# Change custom attributes on project
if custom_attribute_values:
diff --git a/openpype/modules/default_modules/ftrack/event_handlers_user/action_prepare_project.py b/openpype/modules/default_modules/ftrack/event_handlers_user/action_prepare_project.py
index 87d3329179..3759bc81ac 100644
--- a/openpype/modules/default_modules/ftrack/event_handlers_user/action_prepare_project.py
+++ b/openpype/modules/default_modules/ftrack/event_handlers_user/action_prepare_project.py
@@ -3,6 +3,7 @@ import json
from avalon.api import AvalonMongoDB
from openpype.api import ProjectSettings
from openpype.lib import create_project
+from openpype.settings import SaveWarningExc
from openpype_modules.ftrack.lib import (
BaseAction,
@@ -417,7 +418,12 @@ class PrepareProjectLocal(BaseAction):
else:
attributes_entity[key] = value
- project_settings.save()
+ try:
+ project_settings.save()
+ except SaveWarningExc as exc:
+ self.log.info("Few warnings happened during settings save:")
+ for warning in exc.warnings:
+ self.log.info(str(warning))
# Change custom attributes on project
if custom_attribute_values:
diff --git a/openpype/style/__init__.py b/openpype/style/__init__.py
index d763bfdc3c..fd39e93b5d 100644
--- a/openpype/style/__init__.py
+++ b/openpype/style/__init__.py
@@ -12,12 +12,36 @@ _FONT_IDS = None
current_dir = os.path.dirname(os.path.abspath(__file__))
+def _get_colors_raw_data():
+ """Read data file with stylesheet fill values.
+
+ Returns:
+ dict: Loaded data for stylesheet.
+ """
+ data_path = os.path.join(current_dir, "data.json")
+ with open(data_path, "r") as data_stream:
+ data = json.load(data_stream)
+ return data
+
+
def get_colors_data():
+ """Only color data from stylesheet data."""
data = _get_colors_raw_data()
return data.get("color") or {}
def _convert_color_values_to_objects(value):
+ """Parse all string values in dictionary to Color definitions.
+
+ Recursive function calling itself if value is dictionary.
+
+ Args:
+ value (dict, str): String is parsed into color definition object and
+ dictionary is passed into this function.
+
+ Raises:
+ TypeError: If value in color data do not contain string of dictionary.
+ """
if isinstance(value, dict):
output = {}
for _key, _value in value.items():
@@ -32,6 +56,11 @@ def _convert_color_values_to_objects(value):
def get_objected_colors():
+ """Colors parsed from stylesheet data into color definitions.
+
+ Returns:
+ dict: Parsed color objects by keys in data.
+ """
colors_data = get_colors_data()
output = {}
for key, value in colors_data.items():
@@ -39,14 +68,15 @@ def get_objected_colors():
return output
-def _get_colors_raw_data():
- data_path = os.path.join(current_dir, "data.json")
- with open(data_path, "r") as data_stream:
- data = json.load(data_stream)
- return data
-
-
def _load_stylesheet():
+ """Load strylesheet and trigger all related callbacks.
+
+ Style require more than a stylesheet string. Stylesheet string
+ contains paths to resources which must be registered into Qt application
+ and load fonts used in stylesheets.
+
+ Also replace values from stylesheet data into stylesheet text.
+ """
from . import qrc_resources
qrc_resources.qInitResources()
@@ -78,6 +108,7 @@ def _load_stylesheet():
def _load_font():
+ """Load and register fonts into Qt application."""
from Qt import QtGui
global _FONT_IDS
@@ -117,6 +148,7 @@ def _load_font():
def load_stylesheet():
+ """Load and return OpenPype Qt stylesheet."""
global _STYLESHEET_CACHE
if _STYLESHEET_CACHE is None:
_STYLESHEET_CACHE = _load_stylesheet()
@@ -125,4 +157,5 @@ def load_stylesheet():
def app_icon_path():
+ """Path to OpenPype icon."""
return resources.get_openpype_icon_filepath()
diff --git a/openpype/style/color_defs.py b/openpype/style/color_defs.py
index 4d726cc3f3..0f4e145ca0 100644
--- a/openpype/style/color_defs.py
+++ b/openpype/style/color_defs.py
@@ -1,7 +1,27 @@
+"""Color definitions that can be used to parse strings for stylesheet.
+
+Each definition must have available method `get_qcolor` which should return
+`QtGui.QColor` representation of the color.
+
+# TODO create abstract class to force this method implementation
+
+Usage: Some colors may be not be used only in stylesheet but is required to
+use them in code too. To not hardcode these color values into code it is better
+to use same colors that are available fro stylesheets.
+
+It is possible that some colors may not be used in stylesheet at all and thei
+definition is used only in code.
+"""
+
import re
def parse_color(value):
+ """Parse string value of color to one of objected representation.
+
+ Args:
+ value(str): Color definition usable in stylesheet.
+ """
modified_value = value.strip().lower()
if modified_value.startswith("hsla"):
return HSLAColor(value)
@@ -21,12 +41,30 @@ def parse_color(value):
def create_qcolor(*args):
+ """Create QtGui.QColor object.
+
+ Args:
+ *args (tuple): It is possible to pass initialization arguments for
+ Qcolor.
+ """
from Qt import QtGui
return QtGui.QColor(*args)
def min_max_check(value, min_value, max_value):
+ """Validate number value if is in passed range.
+
+ Args:
+ value (int, float): Value which is validated.
+ min_value (int, float): Minimum possible value. Validation is skipped
+ if passed value is None.
+ max_value (int, float): Maximum possible value. Validation is skipped
+ if passed value is None.
+
+ Raises:
+ ValueError: When 'value' is out of specified range.
+ """
if min_value is not None and value < min_value:
raise ValueError("Minimum expected value is '{}' got '{}'".format(
min_value, value
@@ -39,6 +77,16 @@ def min_max_check(value, min_value, max_value):
def int_validation(value, min_value=None, max_value=None):
+ """Validation of integer value within range.
+
+ Args:
+ value (int): Validated value.
+ min_value (int): Minimum possible value.
+ max_value (int): Maximum possible value.
+
+ Raises:
+ TypeError: If 'value' is not 'int' type.
+ """
if not isinstance(value, int):
raise TypeError((
"Invalid type of hue expected 'int' got {}"
@@ -48,6 +96,16 @@ def int_validation(value, min_value=None, max_value=None):
def float_validation(value, min_value=None, max_value=None):
+ """Validation of float value within range.
+
+ Args:
+ value (float): Validated value.
+ min_value (float): Minimum possible value.
+ max_value (float): Maximum possible value.
+
+ Raises:
+ TypeError: If 'value' is not 'float' type.
+ """
if not isinstance(value, float):
raise TypeError((
"Invalid type of hue expected 'int' got {}"
@@ -57,6 +115,11 @@ def float_validation(value, min_value=None, max_value=None):
class UnknownColor:
+ """Color from stylesheet data without known color definition.
+
+ This is backup for unknown color definitions which may be for example
+ constants or definition not yet defined by class.
+ """
def __init__(self, value):
self.value = value
@@ -65,6 +128,14 @@ class UnknownColor:
class HEXColor:
+ """Hex color definition.
+
+ Hex color is defined by '#' and 3 or 6 hex values (0-F).
+
+ Examples:
+ "#fff"
+ "#f3f3f3"
+ """
regex = re.compile(r"[a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?$")
def __init__(self, color_string):
@@ -92,6 +163,7 @@ class HEXColor:
@classmethod
def hex_to_rgb(cls, value):
+ """Convert hex value to rgb."""
hex_value = value.lstrip("#")
if not cls.regex.match(hex_value):
raise ValueError("\"{}\" is not a valid HEX code.".format(value))
@@ -111,6 +183,13 @@ class HEXColor:
class RGBColor:
+ """Color defined by red green and blue values.
+
+ Each color has possible integer range 0-255.
+
+ Examples:
+ "rgb(255, 127, 0)"
+ """
def __init__(self, value):
modified_color = value.lower().strip()
content = modified_color.rstrip(")").lstrip("rgb(")
@@ -146,6 +225,13 @@ class RGBColor:
class RGBAColor:
+ """Color defined by red green, blue and alpha values.
+
+ Each color has possible integer range 0-255.
+
+ Examples:
+ "rgba(255, 127, 0, 127)"
+ """
def __init__(self, value):
modified_color = value.lower().strip()
content = modified_color.rstrip(")").lstrip("rgba(")
@@ -155,7 +241,10 @@ class RGBAColor:
red = int(red_str)
green = int(green_str)
blue = int(blue_str)
- alpha = int(alpha_str)
+ if "." in alpha_str:
+ alpha = int(float(alpha_str) * 100)
+ else:
+ alpha = int(alpha_str)
int_validation(red, 0, 255)
int_validation(green, 0, 255)
@@ -188,6 +277,15 @@ class RGBAColor:
class HSLColor:
+ """Color defined by hue, saturation and light values.
+
+ Hue is defined as integer in rage 0-360. Saturation and light can be
+ defined as float or percent value.
+
+ Examples:
+ "hsl(27, 0.7, 0.3)"
+ "hsl(27, 70%, 30%)"
+ """
def __init__(self, value):
modified_color = value.lower().strip()
content = modified_color.rstrip(")").lstrip("hsl(")
@@ -232,6 +330,16 @@ class HSLColor:
class HSLAColor:
+ """Color defined by hue, saturation, light and alpha values.
+
+ Hue is defined as integer in rage 0-360. Saturation and light can be
+ defined as float (0-1 range) or percent value(0-100%). And alpha
+ as float (0-1 range).
+
+ Examples:
+ "hsl(27, 0.7, 0.3)"
+ "hsl(27, 70%, 30%)"
+ """
def __init__(self, value):
modified_color = value.lower().strip()
content = modified_color.rstrip(")").lstrip("hsla(")
@@ -248,10 +356,8 @@ class HSLAColor:
light = float(light_str.rstrip("%")) / 100
else:
light = float(light_str)
- alpha = float(alpha_str)
- if isinstance(alpha, int):
- alpha = float(alpha)
+ alpha = float(alpha_str)
int_validation(hue, 0, 360)
float_validation(sat, 0, 1)
diff --git a/openpype/style/data.json b/openpype/style/data.json
index a49180fd12..78cc3d3e47 100644
--- a/openpype/style/data.json
+++ b/openpype/style/data.json
@@ -28,27 +28,37 @@
"bg": "#2C313A",
"bg-inputs": "#21252B",
"bg-buttons": "#434a56",
- "bg-button-hover": "hsla(220, 14%, 70%, .3)",
+ "bg-button-hover": "rgba(168, 175, 189, 0.3)",
"bg-inputs-disabled": "#2C313A",
"bg-buttons-disabled": "#434a56",
+ "bg-splitter": "#434a56",
+ "bg-splitter-hover": "rgba(168, 175, 189, 0.3)",
+
"bg-menu-separator": "rgba(75, 83, 98, 127)",
"bg-scroll-handle": "#4B5362",
"bg-view": "#21252B",
"bg-view-header": "#373D48",
- "bg-view-hover": "hsla(220, 14%, 70%, .3)",
+ "bg-view-hover": "rgba(168, 175, 189, .3)",
"bg-view-alternate": "rgb(36, 42, 50)",
"bg-view-disabled": "#434a56",
"bg-view-alternate-disabled": "#2C313A",
- "bg-view-selection": "hsla(200, 60%, 60%, .4)",
- "bg-view-selection-hover": "hsla(200, 60%, 60%, .8)",
+ "bg-view-selection": "rgba(92, 173, 214, .4)",
+ "bg-view-selection-hover": "rgba(92, 173, 214, .8)",
"border": "#373D48",
- "border-hover": "hsla(220, 14%, 70%, .3)",
+ "border-hover": "rgba(168, 175, 189, .3)",
"border-focus": "hsl(200, 60%, 60%)",
+ "loader": {
+ "asset-view": {
+ "selected": "rgba(168, 175, 189, 0.6)",
+ "hover": "rgba(168, 175, 189, 0.3)",
+ "selected-hover": "rgba(168, 175, 189, 0.7)"
+ }
+ },
"publisher": {
"error": "#AA5050",
"success": "#458056",
diff --git a/openpype/style/images/transparent.png b/openpype/style/images/transparent.png
new file mode 100644
index 0000000000..0f2e143b39
Binary files /dev/null and b/openpype/style/images/transparent.png differ
diff --git a/openpype/style/pyqt5_resources.py b/openpype/style/pyqt5_resources.py
index 3dc21be12a..5a3f901840 100644
--- a/openpype/style/pyqt5_resources.py
+++ b/openpype/style/pyqt5_resources.py
@@ -10,19 +10,7 @@ from PyQt5 import QtCore
qt_resource_data = b"\
-\x00\x00\x00\xa0\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
-\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1c\x1f\x24\
-\xc6\x09\x17\x00\x00\x00\x24\x49\x44\x41\x54\x08\xd7\x63\x60\x40\
-\x05\xff\xcf\xc3\x58\x4c\xc8\x5c\x26\x64\x59\x26\x64\xc5\x70\x0e\
-\xa3\x21\x9c\xc3\x68\x88\x61\x1a\x0a\x00\x00\x6d\x84\x09\x75\x37\
-\x9e\xd9\x23\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
-\x00\x00\x07\x30\
+\x00\x00\x07\x06\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x0a\x00\x00\x00\x07\x08\x06\x00\x00\x00\x31\xac\xdc\x63\
@@ -80,10 +68,10 @@ qt_resource_data = b"\
\x65\x3d\x22\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\x36\
\x2d\x32\x2e\x31\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x6f\x64\
\x69\x66\x79\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
-\x2d\x33\x31\x54\x31\x32\x3a\x33\x33\x3a\x31\x34\x2b\x30\x32\x3a\
+\x2d\x33\x31\x54\x31\x32\x3a\x33\x30\x3a\x31\x31\x2b\x30\x32\x3a\
\x30\x30\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x65\x74\x61\x64\
\x61\x74\x61\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
-\x2d\x33\x31\x54\x31\x32\x3a\x33\x33\x3a\x31\x34\x2b\x30\x32\x3a\
+\x2d\x33\x31\x54\x31\x32\x3a\x33\x30\x3a\x31\x31\x2b\x30\x32\x3a\
\x30\x30\x22\x3e\x0a\x20\x20\x20\x3c\x78\x6d\x70\x4d\x4d\x3a\x48\
\x69\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\
\x3a\x53\x65\x71\x3e\x0a\x20\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\
@@ -94,14 +82,14 @@ qt_resource_data = b"\
\x6e\x69\x74\x79\x20\x44\x65\x73\x69\x67\x6e\x65\x72\x20\x31\x2e\
\x39\x2e\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\
\x3a\x77\x68\x65\x6e\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\x2d\x33\
-\x31\x54\x31\x32\x3a\x33\x33\x3a\x31\x34\x2b\x30\x32\x3a\x30\x30\
+\x31\x54\x31\x32\x3a\x33\x30\x3a\x31\x31\x2b\x30\x32\x3a\x30\x30\
\x22\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x53\x65\
\x71\x3e\x0a\x20\x20\x20\x3c\x2f\x78\x6d\x70\x4d\x4d\x3a\x48\x69\
\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x3c\x2f\x72\x64\x66\x3a\x44\
\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e\x0a\x20\x3c\x2f\x72\
\x64\x66\x3a\x52\x44\x46\x3e\x0a\x3c\x2f\x78\x3a\x78\x6d\x70\x6d\
\x65\x74\x61\x3e\x0a\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x65\
-\x6e\x64\x3d\x22\x72\x22\x3f\x3e\x48\x8b\x5b\x5e\x00\x00\x01\x83\
+\x6e\x64\x3d\x22\x72\x22\x3f\x3e\x85\x9d\x9f\x08\x00\x00\x01\x83\
\x69\x43\x43\x50\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\
\x36\x2d\x32\x2e\x31\x00\x00\x28\x91\x75\x91\xcf\x2b\x44\x51\x14\
\xc7\x3f\x66\x68\xfc\x18\x8d\x62\x61\x31\x65\x12\x16\x42\x83\x12\
@@ -128,30 +116,15 @@ qt_resource_data = b"\
\xfd\xec\x73\x74\x07\xd1\x35\xf9\xaa\x4b\xd8\xd9\x85\x0e\x39\xef\
\x59\xf8\x06\x8e\xfd\x67\xf8\xfd\x8a\x18\x97\x00\x00\x00\x09\x70\
\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x97\x49\x44\x41\x54\x18\x95\x6d\xcf\xb1\x6a\x02\x41\
-\x14\x85\xe1\x6f\xb7\xb6\xd0\x27\x48\x3d\x56\x69\x03\xb1\xb4\x48\
-\x3b\x6c\xa5\xf1\x39\xf6\x59\x02\x56\x42\xba\x61\x0a\x0b\x3b\x1b\
-\x1b\x6b\x41\x18\x02\x29\x6d\xe3\xbe\x82\xcd\x06\x16\xd9\xdb\xdd\
-\x9f\xff\x5c\xee\xa9\x62\x2a\x13\x4c\x73\x13\x6e\x46\x26\xa6\xf2\
-\x82\xae\x46\x8b\xdf\x98\xca\xfb\x88\xb4\xc0\x0f\xda\x1a\x5b\x74\
-\xd8\xc7\x54\xc2\x40\x9a\x63\x8f\x3f\x7c\x55\x3d\x7c\xc5\x09\x77\
-\xbc\xa1\xc2\x19\x33\x2c\x72\x13\x2e\xd5\xe0\xc2\x12\x07\x5c\x51\
-\x23\xe0\x23\x37\xe1\xa8\x4f\x0e\x7f\xda\x60\xd7\xaf\x9f\xb9\x09\
-\xdf\x63\x05\xff\xe5\x75\x4c\x65\xf5\xcc\x1f\x0d\x33\x2c\x83\xb6\
-\x06\x44\x83\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
-\x00\x00\x00\xa5\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02\x62\x4b\x47\x44\x00\x9c\x53\x34\xfc\x5d\x00\x00\x00\x09\x70\
-\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x0b\x02\x04\x6d\
-\x98\x1b\x69\x00\x00\x00\x29\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18\x32\x32\x30\x20\x0b\x32\x1a\
-\x32\x30\x30\x42\x98\x10\x41\x46\x43\x14\x13\x50\xb5\xa3\x01\x00\
-\xd6\x10\x07\xd2\x2f\x48\xdf\x4a\x00\x00\x00\x00\x49\x45\x4e\x44\
-\xae\x42\x60\x82\
+\x00\x00\x00\x6d\x49\x44\x41\x54\x18\x95\x75\xcf\xc1\x09\xc2\x50\
+\x10\x84\xe1\xd7\x85\x07\x9b\xd0\x43\x40\xd2\x82\x78\x14\x7b\x30\
+\x57\x21\x8d\x84\x60\x3f\x62\x4b\x7a\x48\xcc\x97\x83\xfb\x30\x04\
+\xdf\x9c\x86\x7f\x67\x99\xdd\x84\x0d\xaa\x54\x10\x6a\x6c\x13\x1e\
+\xbe\xba\xfe\x09\x35\x31\x7b\xe6\x8d\x0f\x26\x1c\x17\xa1\x53\xb0\
+\x11\x87\x0c\x2f\x01\x07\xec\xb0\x0f\x3f\xe1\xbc\xae\x69\xa3\xe6\
+\x85\x77\xf8\x5b\xe9\xf0\xbb\x9f\xfa\xd2\x83\x39\xdc\xa3\x5b\xf3\
+\x19\x2e\xa8\x89\xb5\x30\xf7\x43\xa0\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
\x00\x00\x00\xa0\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -164,6 +137,19 @@ qt_resource_data = b"\
\x05\x73\x3e\xc0\x58\x4c\xc8\x5c\x26\x64\x59\x26\x64\xc5\x70\x4e\
\x8a\x00\x9c\x93\x22\x80\x61\x1a\x0a\x00\x00\x29\x95\x08\xaf\x88\
\xac\xba\x34\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x3b\xdc\
+\x3b\x0c\x9b\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\x73\x3e\x20\x0b\xa4\x08\x30\x32\x30\x20\x0b\xa6\
+\x08\x30\x30\x30\x42\x98\x10\xc1\x14\x01\x14\x13\x50\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90\x5d\x66\x1f\x83\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
\x00\x00\x07\xad\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -289,6 +275,45 @@ qt_resource_data = b"\
\x5e\x78\xa2\x9e\x0e\xa7\x20\x74\x47\x39\x1d\xf6\xe1\x95\x2b\xd6\
\xb1\x44\x8e\x0e\xcb\x58\xf0\x0f\x52\x8a\x79\x18\xdc\xe2\x02\x70\
\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x3b\xdc\
+\x3b\x0c\x9b\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\x73\x3e\x20\x0b\xa4\x08\x30\x32\x30\x20\x0b\xa6\
+\x08\x30\x30\x30\x42\x98\x10\xc1\x14\x01\x14\x13\x50\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90\x5d\x66\x1f\x83\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1d\x00\xb0\
+\xd5\x35\xa3\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x06\xfe\x9f\x67\x60\x60\x42\x30\xa1\x1c\x08\x93\x81\x81\x09\xc1\
+\x64\x60\x60\x62\x60\x60\x34\x44\xe2\x20\x73\x19\x90\x8d\x40\x02\
+\x00\x64\x40\x09\x75\x86\xb3\xad\x9c\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x3b\xdc\
+\x3b\x0c\x9b\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\x73\x3e\x20\x0b\xa4\x08\x30\x32\x30\x20\x0b\xa6\
+\x08\x30\x30\x30\x42\x98\x10\xc1\x14\x01\x14\x13\x50\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90\x5d\x66\x1f\x83\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
\x00\x00\x00\xa0\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -313,18 +338,26 @@ qt_resource_data = b"\
\x0d\xe6\x7c\x80\xb1\x18\x91\x05\x52\x04\xe0\x42\x08\x15\x29\x02\
\x0c\x0c\x8c\xc8\x02\x08\x95\x68\x00\x00\xac\xac\x07\x90\x4e\x65\
\x34\xac\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
-\x00\x00\x00\x9e\
+\x00\x00\x00\x45\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53\xde\
+\x00\x00\x00\x0c\x49\x44\x41\x54\x08\x99\x63\x60\x60\x60\x00\x00\
+\x00\x04\x00\x01\xa3\x0a\x15\xe3\x00\x00\x00\x00\x49\x45\x4e\x44\
+\xae\x42\x60\x82\
+\x00\x00\x00\xa5\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x02\x62\x4b\x47\x44\x00\x9c\x53\x34\xfc\x5d\x00\x00\x00\x09\x70\
\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x0f\xfd\
-\x8f\xf8\x2e\x00\x00\x00\x22\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1\x42\x48\x2a\x0c\x19\
-\x18\x18\x91\x05\x10\x2a\xd1\x00\x00\xca\xb5\x07\xd2\x76\xbb\xb2\
-\xc5\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x0b\x02\x04\x6d\
+\x98\x1b\x69\x00\x00\x00\x29\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18\x32\x32\x30\x20\x0b\x32\x1a\
+\x32\x30\x30\x42\x98\x10\x41\x46\x43\x14\x13\x50\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2\x2f\x48\xdf\x4a\x00\x00\x00\x00\x49\x45\x4e\x44\
+\xae\x42\x60\x82\
\x00\x00\x00\xa5\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -341,15 +374,170 @@ qt_resource_data = b"\
\x00\x00\x00\xa6\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x3b\xdc\
-\x3b\x0c\x9b\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x00\x8c\x0c\x0c\x73\x3e\x20\x0b\xa4\x08\x30\x32\x30\x20\x0b\xa6\
-\x08\x30\x30\x30\x42\x98\x10\xc1\x14\x01\x14\x13\x50\xb5\xa3\x01\
-\x00\xc6\xb9\x07\x90\x5d\x66\x1f\x83\x00\x00\x00\x00\x49\x45\x4e\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1f\x20\xb9\
+\x8d\x77\xe9\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x06\xe6\x7c\x60\x60\x60\x42\x30\xa1\x1c\x08\x93\x81\x81\x09\xc1\
+\x64\x60\x60\x62\x60\x48\x11\x40\xe2\x20\x73\x19\x90\x8d\x40\x02\
+\x00\x23\xed\x08\xaf\x64\x9f\x0f\x15\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa5\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\x9c\x53\x34\xfc\x5d\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x0b\x02\x04\x6d\
+\x98\x1b\x69\x00\x00\x00\x29\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18\x32\x32\x30\x20\x0b\x32\x1a\
+\x32\x30\x30\x42\x98\x10\x41\x46\x43\x14\x13\x50\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2\x2f\x48\xdf\x4a\x00\x00\x00\x00\x49\x45\x4e\x44\
+\xae\x42\x60\x82\
+\x00\x00\x07\x30\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x0a\x00\x00\x00\x07\x08\x06\x00\x00\x00\x31\xac\xdc\x63\
+\x00\x00\x04\xb0\x69\x54\x58\x74\x58\x4d\x4c\x3a\x63\x6f\x6d\x2e\
+\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\x00\x00\x00\x3c\x3f\
+\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\x69\x6e\x3d\x22\xef\
+\xbb\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\x30\x4d\x70\x43\x65\
+\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\x7a\x6b\x63\x39\x64\
+\x22\x3f\x3e\x0a\x3c\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x20\x78\
+\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\x62\x65\x3a\x6e\x73\
+\x3a\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\x6d\x70\x74\x6b\x3d\
+\x22\x58\x4d\x50\x20\x43\x6f\x72\x65\x20\x35\x2e\x35\x2e\x30\x22\
+\x3e\x0a\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\
+\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\
+\x73\x23\x22\x3e\x0a\x20\x20\x3c\x72\x64\x66\x3a\x44\x65\x73\x63\
+\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\
+\x74\x3d\x22\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x65\
+\x78\x69\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\
+\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x65\x78\x69\x66\x2f\x31\x2e\
+\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x74\x69\
+\x66\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\
+\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x74\x69\x66\x66\x2f\x31\x2e\x30\
+\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x70\x68\x6f\
+\x74\x6f\x73\x68\x6f\x70\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\
+\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x70\x68\x6f\x74\
+\x6f\x73\x68\x6f\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\
+\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\
+\x61\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x78\x6d\x70\x4d\x4d\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\x61\
+\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\x2f\x22\x0a\x20\x20\x20\x20\x78\
+\x6d\x6c\x6e\x73\x3a\x73\x74\x45\x76\x74\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\
+\x78\x61\x70\x2f\x31\x2e\x30\x2f\x73\x54\x79\x70\x65\x2f\x52\x65\
+\x73\x6f\x75\x72\x63\x65\x45\x76\x65\x6e\x74\x23\x22\x0a\x20\x20\
+\x20\x65\x78\x69\x66\x3a\x50\x69\x78\x65\x6c\x58\x44\x69\x6d\x65\
+\x6e\x73\x69\x6f\x6e\x3d\x22\x31\x30\x22\x0a\x20\x20\x20\x65\x78\
+\x69\x66\x3a\x50\x69\x78\x65\x6c\x59\x44\x69\x6d\x65\x6e\x73\x69\
+\x6f\x6e\x3d\x22\x37\x22\x0a\x20\x20\x20\x65\x78\x69\x66\x3a\x43\
+\x6f\x6c\x6f\x72\x53\x70\x61\x63\x65\x3d\x22\x31\x22\x0a\x20\x20\
+\x20\x74\x69\x66\x66\x3a\x49\x6d\x61\x67\x65\x57\x69\x64\x74\x68\
+\x3d\x22\x31\x30\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x49\x6d\
+\x61\x67\x65\x4c\x65\x6e\x67\x74\x68\x3d\x22\x37\x22\x0a\x20\x20\
+\x20\x74\x69\x66\x66\x3a\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\
+\x55\x6e\x69\x74\x3d\x22\x32\x22\x0a\x20\x20\x20\x74\x69\x66\x66\
+\x3a\x58\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\
+\x2e\x30\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x59\x52\x65\x73\
+\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\x2e\x30\x22\x0a\x20\
+\x20\x20\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3a\x43\x6f\x6c\x6f\
+\x72\x4d\x6f\x64\x65\x3d\x22\x33\x22\x0a\x20\x20\x20\x70\x68\x6f\
+\x74\x6f\x73\x68\x6f\x70\x3a\x49\x43\x43\x50\x72\x6f\x66\x69\x6c\
+\x65\x3d\x22\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\x36\
+\x2d\x32\x2e\x31\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x6f\x64\
+\x69\x66\x79\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x33\x33\x3a\x31\x34\x2b\x30\x32\x3a\
+\x30\x30\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x65\x74\x61\x64\
+\x61\x74\x61\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
+\x2d\x33\x31\x54\x31\x32\x3a\x33\x33\x3a\x31\x34\x2b\x30\x32\x3a\
+\x30\x30\x22\x3e\x0a\x20\x20\x20\x3c\x78\x6d\x70\x4d\x4d\x3a\x48\
+\x69\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\
+\x3a\x53\x65\x71\x3e\x0a\x20\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\
+\x6c\x69\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\x3a\x61\
+\x63\x74\x69\x6f\x6e\x3d\x22\x70\x72\x6f\x64\x75\x63\x65\x64\x22\
+\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\x3a\x73\x6f\x66\
+\x74\x77\x61\x72\x65\x41\x67\x65\x6e\x74\x3d\x22\x41\x66\x66\x69\
+\x6e\x69\x74\x79\x20\x44\x65\x73\x69\x67\x6e\x65\x72\x20\x31\x2e\
+\x39\x2e\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\
+\x3a\x77\x68\x65\x6e\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\x2d\x33\
+\x31\x54\x31\x32\x3a\x33\x33\x3a\x31\x34\x2b\x30\x32\x3a\x30\x30\
+\x22\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x53\x65\
+\x71\x3e\x0a\x20\x20\x20\x3c\x2f\x78\x6d\x70\x4d\x4d\x3a\x48\x69\
+\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x3c\x2f\x72\x64\x66\x3a\x44\
+\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e\x0a\x20\x3c\x2f\x72\
+\x64\x66\x3a\x52\x44\x46\x3e\x0a\x3c\x2f\x78\x3a\x78\x6d\x70\x6d\
+\x65\x74\x61\x3e\x0a\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x65\
+\x6e\x64\x3d\x22\x72\x22\x3f\x3e\x48\x8b\x5b\x5e\x00\x00\x01\x83\
+\x69\x43\x43\x50\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\
+\x36\x2d\x32\x2e\x31\x00\x00\x28\x91\x75\x91\xcf\x2b\x44\x51\x14\
+\xc7\x3f\x66\x68\xfc\x18\x8d\x62\x61\x31\x65\x12\x16\x42\x83\x12\
+\x1b\x8b\x99\x18\x0a\x8b\x99\x51\x7e\x6d\x66\x9e\x79\x33\x6a\xde\
+\x78\xbd\x37\xd2\x64\xab\x6c\xa7\x28\xb1\xf1\x6b\xc1\x5f\xc0\x56\
+\x59\x2b\x45\xa4\x64\xa7\xac\x89\x0d\x7a\xce\x9b\x51\x23\x99\x73\
+\x3b\xf7\x7c\xee\xf7\xde\x73\xba\xf7\x5c\x70\x44\xd3\x8a\x66\x56\
+\xfa\x41\xcb\x64\x8d\x70\x28\xe0\x9b\x99\x9d\xf3\xb9\x9e\xa8\xa2\
+\x85\x1a\x3a\xf1\xc6\x14\x53\x9f\x8c\x8c\x46\x29\x6b\xef\xb7\x54\
+\xd8\xf1\xba\xdb\xae\x55\xfe\xdc\xbf\x56\xb7\x98\x30\x15\xa8\xa8\
+\x16\x1e\x56\x74\x23\x2b\x3c\x26\x3c\xb1\x9a\xd5\x6d\xde\x12\x6e\
+\x52\x52\xb1\x45\xe1\x13\xe1\x2e\x43\x2e\x28\x7c\x63\xeb\xf1\x22\
+\x3f\xdb\x9c\x2c\xf2\xa7\xcd\x46\x34\x1c\x04\x47\x83\xb0\x2f\xf9\
+\x8b\xe3\xbf\x58\x49\x19\x9a\xb0\xbc\x9c\x36\x2d\xbd\xa2\xfc\xdc\
+\xc7\x7e\x89\x3b\x91\x99\x8e\x48\x6c\x15\xf7\x62\x12\x26\x44\x00\
+\x1f\xe3\x8c\x10\x64\x80\x5e\x86\x64\x1e\xa0\x9b\x3e\x7a\x64\x45\
+\x99\x7c\x7f\x21\x7f\x8a\x65\xc9\x55\x64\xd6\xc9\x61\xb0\x44\x92\
+\x14\x59\xba\x44\x5d\x91\xea\x09\x89\xaa\xe8\x09\x19\x69\x72\x76\
+\xff\xff\xf6\xd5\x54\xfb\xfb\x8a\xd5\xdd\x01\xa8\x7a\xb4\xac\xd7\
+\x76\x70\x6d\xc2\x57\xde\xb2\x3e\x0e\x2c\xeb\xeb\x10\x9c\x0f\x70\
+\x9e\x29\xe5\x2f\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\x9e\x75\
+\x38\xbd\x28\x69\xf1\x6d\x38\xdb\x80\xe6\x7b\x3d\x66\xc4\x0a\x92\
+\x53\xdc\xa1\xaa\xf0\x72\x0c\xf5\xb3\xd0\x78\x05\xb5\xf3\xc5\x9e\
+\xfd\xec\x73\x74\x07\xd1\x35\xf9\xaa\x4b\xd8\xd9\x85\x0e\x39\xef\
+\x59\xf8\x06\x8e\xfd\x67\xf8\xfd\x8a\x18\x97\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x97\x49\x44\x41\x54\x18\x95\x6d\xcf\xb1\x6a\x02\x41\
+\x14\x85\xe1\x6f\xb7\xb6\xd0\x27\x48\x3d\x56\x69\x03\xb1\xb4\x48\
+\x3b\x6c\xa5\xf1\x39\xf6\x59\x02\x56\x42\xba\x61\x0a\x0b\x3b\x1b\
+\x1b\x6b\x41\x18\x02\x29\x6d\xe3\xbe\x82\xcd\x06\x16\xd9\xdb\xdd\
+\x9f\xff\x5c\xee\xa9\x62\x2a\x13\x4c\x73\x13\x6e\x46\x26\xa6\xf2\
+\x82\xae\x46\x8b\xdf\x98\xca\xfb\x88\xb4\xc0\x0f\xda\x1a\x5b\x74\
+\xd8\xc7\x54\xc2\x40\x9a\x63\x8f\x3f\x7c\x55\x3d\x7c\xc5\x09\x77\
+\xbc\xa1\xc2\x19\x33\x2c\x72\x13\x2e\xd5\xe0\xc2\x12\x07\x5c\x51\
+\x23\xe0\x23\x37\xe1\xa8\x4f\x0e\x7f\xda\x60\xd7\xaf\x9f\xb9\x09\
+\xdf\x63\x05\xff\xe5\x75\x4c\x65\xf5\xcc\x1f\x0d\x33\x2c\x83\xb6\
+\x06\x44\x83\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa0\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1c\x1f\x24\
+\xc6\x09\x17\x00\x00\x00\x24\x49\x44\x41\x54\x08\xd7\x63\x60\x40\
+\x05\xff\xcf\xc3\x58\x4c\xc8\x5c\x26\x64\x59\x26\x64\xc5\x70\x0e\
+\xa3\x21\x9c\xc3\x68\x88\x61\x1a\x0a\x00\x00\x6d\x84\x09\x75\x37\
+\x9e\xd9\x23\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x00\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1d\x00\xb0\
+\xd5\x35\xa3\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x06\xfe\x9f\x67\x60\x60\x42\x30\xa1\x1c\x08\x93\x81\x81\x09\xc1\
+\x64\x60\x60\x62\x60\x60\x34\x44\xe2\x20\x73\x19\x90\x8d\x40\x02\
+\x00\x64\x40\x09\x75\x86\xb3\xad\x9c\x00\x00\x00\x00\x49\x45\x4e\
\x44\xae\x42\x60\x82\
\x00\x00\x07\xdd\
\x89\
@@ -479,45 +667,6 @@ qt_resource_data = b"\
\x71\x5b\x73\x5c\x40\x48\xa5\xdd\x61\x81\x0d\x9e\x6b\x8e\xff\xfd\
\xcf\x3f\xcc\x31\xe9\x01\x1c\x00\x73\x52\x2d\x71\xe4\x4a\x1b\x69\
\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
-\x00\x00\x00\xa6\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
-\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x3b\xdc\
-\x3b\x0c\x9b\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x00\x8c\x0c\x0c\x73\x3e\x20\x0b\xa4\x08\x30\x32\x30\x20\x0b\xa6\
-\x08\x30\x30\x30\x42\x98\x10\xc1\x14\x01\x14\x13\x50\xb5\xa3\x01\
-\x00\xc6\xb9\x07\x90\x5d\x66\x1f\x83\x00\x00\x00\x00\x49\x45\x4e\
-\x44\xae\x42\x60\x82\
-\x00\x00\x00\xa5\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02\x62\x4b\x47\x44\x00\x9c\x53\x34\xfc\x5d\x00\x00\x00\x09\x70\
-\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x0b\x02\x04\x6d\
-\x98\x1b\x69\x00\x00\x00\x29\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18\x32\x32\x30\x20\x0b\x32\x1a\
-\x32\x30\x30\x42\x98\x10\x41\x46\x43\x14\x13\x50\xb5\xa3\x01\x00\
-\xd6\x10\x07\xd2\x2f\x48\xdf\x4a\x00\x00\x00\x00\x49\x45\x4e\x44\
-\xae\x42\x60\x82\
-\x00\x00\x00\xa6\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
-\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1f\x20\xb9\
-\x8d\x77\xe9\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x06\xe6\x7c\x60\x60\x60\x42\x30\xa1\x1c\x08\x93\x81\x81\x09\xc1\
-\x64\x60\x60\x62\x60\x48\x11\x40\xe2\x20\x73\x19\x90\x8d\x40\x02\
-\x00\x23\xed\x08\xaf\x64\x9f\x0f\x15\x00\x00\x00\x00\x49\x45\x4e\
-\x44\xae\x42\x60\x82\
\x00\x00\x00\x9e\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -530,160 +679,18 @@ qt_resource_data = b"\
\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1\x42\x48\x2a\x0c\x19\
\x18\x18\x91\x05\x10\x2a\xd1\x00\x00\xca\xb5\x07\xd2\x76\xbb\xb2\
\xc5\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
-\x00\x00\x00\xa6\
+\x00\x00\x00\x9e\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce\x7c\x4e\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x3b\xdc\
-\x3b\x0c\x9b\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x00\x8c\x0c\x0c\x73\x3e\x20\x0b\xa4\x08\x30\x32\x30\x20\x0b\xa6\
-\x08\x30\x30\x30\x42\x98\x10\xc1\x14\x01\x14\x13\x50\xb5\xa3\x01\
-\x00\xc6\xb9\x07\x90\x5d\x66\x1f\x83\x00\x00\x00\x00\x49\x45\x4e\
-\x44\xae\x42\x60\x82\
-\x00\x00\x00\xa6\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
-\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1d\x00\xb0\
-\xd5\x35\xa3\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x06\xfe\x9f\x67\x60\x60\x42\x30\xa1\x1c\x08\x93\x81\x81\x09\xc1\
-\x64\x60\x60\x62\x60\x60\x34\x44\xe2\x20\x73\x19\x90\x8d\x40\x02\
-\x00\x64\x40\x09\x75\x86\xb3\xad\x9c\x00\x00\x00\x00\x49\x45\x4e\
-\x44\xae\x42\x60\x82\
-\x00\x00\x00\xa6\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02\x62\x4b\x47\x44\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09\x70\
-\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x14\x1d\x00\xb0\
-\xd5\x35\xa3\x00\x00\x00\x2a\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
-\x06\xfe\x9f\x67\x60\x60\x42\x30\xa1\x1c\x08\x93\x81\x81\x09\xc1\
-\x64\x60\x60\x62\x60\x60\x34\x44\xe2\x20\x73\x19\x90\x8d\x40\x02\
-\x00\x64\x40\x09\x75\x86\xb3\xad\x9c\x00\x00\x00\x00\x49\x45\x4e\
-\x44\xae\x42\x60\x82\
-\x00\x00\x07\x06\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x0a\x00\x00\x00\x07\x08\x06\x00\x00\x00\x31\xac\xdc\x63\
-\x00\x00\x04\xb0\x69\x54\x58\x74\x58\x4d\x4c\x3a\x63\x6f\x6d\x2e\
-\x61\x64\x6f\x62\x65\x2e\x78\x6d\x70\x00\x00\x00\x00\x00\x3c\x3f\
-\x78\x70\x61\x63\x6b\x65\x74\x20\x62\x65\x67\x69\x6e\x3d\x22\xef\
-\xbb\xbf\x22\x20\x69\x64\x3d\x22\x57\x35\x4d\x30\x4d\x70\x43\x65\
-\x68\x69\x48\x7a\x72\x65\x53\x7a\x4e\x54\x63\x7a\x6b\x63\x39\x64\
-\x22\x3f\x3e\x0a\x3c\x78\x3a\x78\x6d\x70\x6d\x65\x74\x61\x20\x78\
-\x6d\x6c\x6e\x73\x3a\x78\x3d\x22\x61\x64\x6f\x62\x65\x3a\x6e\x73\
-\x3a\x6d\x65\x74\x61\x2f\x22\x20\x78\x3a\x78\x6d\x70\x74\x6b\x3d\
-\x22\x58\x4d\x50\x20\x43\x6f\x72\x65\x20\x35\x2e\x35\x2e\x30\x22\
-\x3e\x0a\x20\x3c\x72\x64\x66\x3a\x52\x44\x46\x20\x78\x6d\x6c\x6e\
-\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
-\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\
-\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\
-\x73\x23\x22\x3e\x0a\x20\x20\x3c\x72\x64\x66\x3a\x44\x65\x73\x63\
-\x72\x69\x70\x74\x69\x6f\x6e\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\
-\x74\x3d\x22\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x65\
-\x78\x69\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\
-\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x65\x78\x69\x66\x2f\x31\x2e\
-\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x74\x69\
-\x66\x66\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\
-\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x74\x69\x66\x66\x2f\x31\x2e\x30\
-\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x70\x68\x6f\
-\x74\x6f\x73\x68\x6f\x70\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x6e\
-\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x70\x68\x6f\x74\
-\x6f\x73\x68\x6f\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\
-\x78\x6d\x6c\x6e\x73\x3a\x78\x6d\x70\x3d\x22\x68\x74\x74\x70\x3a\
-\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\
-\x61\x70\x2f\x31\x2e\x30\x2f\x22\x0a\x20\x20\x20\x20\x78\x6d\x6c\
-\x6e\x73\x3a\x78\x6d\x70\x4d\x4d\x3d\x22\x68\x74\x74\x70\x3a\x2f\
-\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\x78\x61\
-\x70\x2f\x31\x2e\x30\x2f\x6d\x6d\x2f\x22\x0a\x20\x20\x20\x20\x78\
-\x6d\x6c\x6e\x73\x3a\x73\x74\x45\x76\x74\x3d\x22\x68\x74\x74\x70\
-\x3a\x2f\x2f\x6e\x73\x2e\x61\x64\x6f\x62\x65\x2e\x63\x6f\x6d\x2f\
-\x78\x61\x70\x2f\x31\x2e\x30\x2f\x73\x54\x79\x70\x65\x2f\x52\x65\
-\x73\x6f\x75\x72\x63\x65\x45\x76\x65\x6e\x74\x23\x22\x0a\x20\x20\
-\x20\x65\x78\x69\x66\x3a\x50\x69\x78\x65\x6c\x58\x44\x69\x6d\x65\
-\x6e\x73\x69\x6f\x6e\x3d\x22\x31\x30\x22\x0a\x20\x20\x20\x65\x78\
-\x69\x66\x3a\x50\x69\x78\x65\x6c\x59\x44\x69\x6d\x65\x6e\x73\x69\
-\x6f\x6e\x3d\x22\x37\x22\x0a\x20\x20\x20\x65\x78\x69\x66\x3a\x43\
-\x6f\x6c\x6f\x72\x53\x70\x61\x63\x65\x3d\x22\x31\x22\x0a\x20\x20\
-\x20\x74\x69\x66\x66\x3a\x49\x6d\x61\x67\x65\x57\x69\x64\x74\x68\
-\x3d\x22\x31\x30\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x49\x6d\
-\x61\x67\x65\x4c\x65\x6e\x67\x74\x68\x3d\x22\x37\x22\x0a\x20\x20\
-\x20\x74\x69\x66\x66\x3a\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\
-\x55\x6e\x69\x74\x3d\x22\x32\x22\x0a\x20\x20\x20\x74\x69\x66\x66\
-\x3a\x58\x52\x65\x73\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\
-\x2e\x30\x22\x0a\x20\x20\x20\x74\x69\x66\x66\x3a\x59\x52\x65\x73\
-\x6f\x6c\x75\x74\x69\x6f\x6e\x3d\x22\x37\x32\x2e\x30\x22\x0a\x20\
-\x20\x20\x70\x68\x6f\x74\x6f\x73\x68\x6f\x70\x3a\x43\x6f\x6c\x6f\
-\x72\x4d\x6f\x64\x65\x3d\x22\x33\x22\x0a\x20\x20\x20\x70\x68\x6f\
-\x74\x6f\x73\x68\x6f\x70\x3a\x49\x43\x43\x50\x72\x6f\x66\x69\x6c\
-\x65\x3d\x22\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\x36\
-\x2d\x32\x2e\x31\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x6f\x64\
-\x69\x66\x79\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
-\x2d\x33\x31\x54\x31\x32\x3a\x33\x30\x3a\x31\x31\x2b\x30\x32\x3a\
-\x30\x30\x22\x0a\x20\x20\x20\x78\x6d\x70\x3a\x4d\x65\x74\x61\x64\
-\x61\x74\x61\x44\x61\x74\x65\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\
-\x2d\x33\x31\x54\x31\x32\x3a\x33\x30\x3a\x31\x31\x2b\x30\x32\x3a\
-\x30\x30\x22\x3e\x0a\x20\x20\x20\x3c\x78\x6d\x70\x4d\x4d\x3a\x48\
-\x69\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x20\x20\x3c\x72\x64\x66\
-\x3a\x53\x65\x71\x3e\x0a\x20\x20\x20\x20\x20\x3c\x72\x64\x66\x3a\
-\x6c\x69\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\x3a\x61\
-\x63\x74\x69\x6f\x6e\x3d\x22\x70\x72\x6f\x64\x75\x63\x65\x64\x22\
-\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\x3a\x73\x6f\x66\
-\x74\x77\x61\x72\x65\x41\x67\x65\x6e\x74\x3d\x22\x41\x66\x66\x69\
-\x6e\x69\x74\x79\x20\x44\x65\x73\x69\x67\x6e\x65\x72\x20\x31\x2e\
-\x39\x2e\x32\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x74\x45\x76\x74\
-\x3a\x77\x68\x65\x6e\x3d\x22\x32\x30\x32\x31\x2d\x30\x35\x2d\x33\
-\x31\x54\x31\x32\x3a\x33\x30\x3a\x31\x31\x2b\x30\x32\x3a\x30\x30\
-\x22\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x72\x64\x66\x3a\x53\x65\
-\x71\x3e\x0a\x20\x20\x20\x3c\x2f\x78\x6d\x70\x4d\x4d\x3a\x48\x69\
-\x73\x74\x6f\x72\x79\x3e\x0a\x20\x20\x3c\x2f\x72\x64\x66\x3a\x44\
-\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e\x0a\x20\x3c\x2f\x72\
-\x64\x66\x3a\x52\x44\x46\x3e\x0a\x3c\x2f\x78\x3a\x78\x6d\x70\x6d\
-\x65\x74\x61\x3e\x0a\x3c\x3f\x78\x70\x61\x63\x6b\x65\x74\x20\x65\
-\x6e\x64\x3d\x22\x72\x22\x3f\x3e\x85\x9d\x9f\x08\x00\x00\x01\x83\
-\x69\x43\x43\x50\x73\x52\x47\x42\x20\x49\x45\x43\x36\x31\x39\x36\
-\x36\x2d\x32\x2e\x31\x00\x00\x28\x91\x75\x91\xcf\x2b\x44\x51\x14\
-\xc7\x3f\x66\x68\xfc\x18\x8d\x62\x61\x31\x65\x12\x16\x42\x83\x12\
-\x1b\x8b\x99\x18\x0a\x8b\x99\x51\x7e\x6d\x66\x9e\x79\x33\x6a\xde\
-\x78\xbd\x37\xd2\x64\xab\x6c\xa7\x28\xb1\xf1\x6b\xc1\x5f\xc0\x56\
-\x59\x2b\x45\xa4\x64\xa7\xac\x89\x0d\x7a\xce\x9b\x51\x23\x99\x73\
-\x3b\xf7\x7c\xee\xf7\xde\x73\xba\xf7\x5c\x70\x44\xd3\x8a\x66\x56\
-\xfa\x41\xcb\x64\x8d\x70\x28\xe0\x9b\x99\x9d\xf3\xb9\x9e\xa8\xa2\
-\x85\x1a\x3a\xf1\xc6\x14\x53\x9f\x8c\x8c\x46\x29\x6b\xef\xb7\x54\
-\xd8\xf1\xba\xdb\xae\x55\xfe\xdc\xbf\x56\xb7\x98\x30\x15\xa8\xa8\
-\x16\x1e\x56\x74\x23\x2b\x3c\x26\x3c\xb1\x9a\xd5\x6d\xde\x12\x6e\
-\x52\x52\xb1\x45\xe1\x13\xe1\x2e\x43\x2e\x28\x7c\x63\xeb\xf1\x22\
-\x3f\xdb\x9c\x2c\xf2\xa7\xcd\x46\x34\x1c\x04\x47\x83\xb0\x2f\xf9\
-\x8b\xe3\xbf\x58\x49\x19\x9a\xb0\xbc\x9c\x36\x2d\xbd\xa2\xfc\xdc\
-\xc7\x7e\x89\x3b\x91\x99\x8e\x48\x6c\x15\xf7\x62\x12\x26\x44\x00\
-\x1f\xe3\x8c\x10\x64\x80\x5e\x86\x64\x1e\xa0\x9b\x3e\x7a\x64\x45\
-\x99\x7c\x7f\x21\x7f\x8a\x65\xc9\x55\x64\xd6\xc9\x61\xb0\x44\x92\
-\x14\x59\xba\x44\x5d\x91\xea\x09\x89\xaa\xe8\x09\x19\x69\x72\x76\
-\xff\xff\xf6\xd5\x54\xfb\xfb\x8a\xd5\xdd\x01\xa8\x7a\xb4\xac\xd7\
-\x76\x70\x6d\xc2\x57\xde\xb2\x3e\x0e\x2c\xeb\xeb\x10\x9c\x0f\x70\
-\x9e\x29\xe5\x2f\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\x9e\x75\
-\x38\xbd\x28\x69\xf1\x6d\x38\xdb\x80\xe6\x7b\x3d\x66\xc4\x0a\x92\
-\x53\xdc\xa1\xaa\xf0\x72\x0c\xf5\xb3\xd0\x78\x05\xb5\xf3\xc5\x9e\
-\xfd\xec\x73\x74\x07\xd1\x35\xf9\xaa\x4b\xd8\xd9\x85\x0e\x39\xef\
-\x59\xf8\x06\x8e\xfd\x67\xf8\xfd\x8a\x18\x97\x00\x00\x00\x09\x70\
-\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x6d\x49\x44\x41\x54\x18\x95\x75\xcf\xc1\x09\xc2\x50\
-\x10\x84\xe1\xd7\x85\x07\x9b\xd0\x43\x40\xd2\x82\x78\x14\x7b\x30\
-\x57\x21\x8d\x84\x60\x3f\x62\x4b\x7a\x48\xcc\x97\x83\xfb\x30\x04\
-\xdf\x9c\x86\x7f\x67\x99\xdd\x84\x0d\xaa\x54\x10\x6a\x6c\x13\x1e\
-\xbe\xba\xfe\x09\x35\x31\x7b\xe6\x8d\x0f\x26\x1c\x17\xa1\x53\xb0\
-\x11\x87\x0c\x2f\x01\x07\xec\xb0\x0f\x3f\xe1\xbc\xae\x69\xa3\xe6\
-\x85\x77\xf8\x5b\xe9\xf0\xbb\x9f\xfa\xd2\x83\x39\xdc\xa3\x5b\xf3\
-\x19\x2e\xa8\x89\xb5\x30\xf7\x43\xa0\x00\x00\x00\x00\x49\x45\x4e\
-\x44\xae\x42\x60\x82\
+\x00\x00\x00\x07\x74\x49\x4d\x45\x07\xdc\x08\x17\x08\x15\x0f\xfd\
+\x8f\xf8\x2e\x00\x00\x00\x22\x49\x44\x41\x54\x08\xd7\x63\x60\xc0\
+\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1\x42\x48\x2a\x0c\x19\
+\x18\x18\x91\x05\x10\x2a\xd1\x00\x00\xca\xb5\x07\xd2\x76\xbb\xb2\
+\xc5\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
"
qt_resource_name = b"\
@@ -696,119 +703,124 @@ qt_resource_name = b"\
\x00\x69\
\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x73\
\x00\x0f\
-\x02\x9f\x05\x87\
-\x00\x72\
-\x00\x69\x00\x67\x00\x68\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\x00\x12\
-\x05\x8f\x9d\x07\
+\x06\x53\x25\xa7\
\x00\x62\
-\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x6f\x00\x70\x00\x65\x00\x6e\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\
-\x00\x67\
-\x00\x1b\
-\x03\x5a\x32\x27\
-\x00\x63\
-\x00\x6f\x00\x6d\x00\x62\x00\x6f\x00\x62\x00\x6f\x00\x78\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\
-\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x6f\x00\x70\x00\x65\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x18\
\x03\x8e\xde\x67\
\x00\x72\
\x00\x69\x00\x67\x00\x68\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\
\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\x00\x11\
-\x0b\xda\x30\xa7\
-\x00\x62\
-\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\
-\x00\x12\
-\x03\x8d\x04\x47\
-\x00\x72\
-\x00\x69\x00\x67\x00\x68\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\
-\x00\x67\
-\x00\x15\
-\x0f\xf3\xc0\x07\
-\x00\x75\
-\x00\x70\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\
-\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\x00\x0f\
-\x01\x73\x8b\x07\
-\x00\x75\
-\x00\x70\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\x00\x0e\
-\x04\xa2\xfc\xa7\
-\x00\x64\
-\x00\x6f\x00\x77\x00\x6e\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\x00\x12\
-\x01\x2e\x03\x27\
-\x00\x63\
-\x00\x6f\x00\x6d\x00\x62\x00\x6f\x00\x62\x00\x6f\x00\x78\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\
-\x00\x67\
-\x00\x14\
-\x04\x5e\x2d\xa7\
-\x00\x62\
-\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x64\x00\x5f\x00\x6f\x00\x6e\x00\x2e\
-\x00\x70\x00\x6e\x00\x67\
-\x00\x17\
-\x0c\xab\x51\x07\
-\x00\x64\
-\x00\x6f\x00\x77\x00\x6e\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\
-\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\x00\x11\
-\x01\x1f\xc3\x87\
-\x00\x64\
-\x00\x6f\x00\x77\x00\x6e\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\
-\x00\x17\
-\x0c\x65\xce\x07\
-\x00\x6c\
-\x00\x65\x00\x66\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\
-\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\x00\x0c\
-\x06\xe6\xe6\x67\
-\x00\x75\
-\x00\x70\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x15\
\x03\x27\x72\x67\
\x00\x63\
\x00\x6f\x00\x6d\x00\x62\x00\x6f\x00\x62\x00\x6f\x00\x78\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\
\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x11\
+\x0b\xda\x30\xa7\
+\x00\x62\
+\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\
+\x00\x17\
+\x0c\xab\x51\x07\
+\x00\x64\
+\x00\x6f\x00\x77\x00\x6e\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\
+\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x11\
\x00\xb8\x8c\x07\
\x00\x6c\
\x00\x65\x00\x66\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
\
+\x00\x12\
+\x01\x2e\x03\x27\
+\x00\x63\
+\x00\x6f\x00\x6d\x00\x62\x00\x6f\x00\x62\x00\x6f\x00\x78\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\
+\x00\x67\
+\x00\x0f\
+\x02\x9f\x05\x87\
+\x00\x72\
+\x00\x69\x00\x67\x00\x68\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x15\
+\x0f\xf3\xc0\x07\
+\x00\x75\
+\x00\x70\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\
+\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x0f\
+\x0c\xe2\x68\x67\
+\x00\x74\
+\x00\x72\x00\x61\x00\x6e\x00\x73\x00\x70\x00\x61\x00\x72\x00\x65\x00\x6e\x00\x74\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x0e\
+\x04\xa2\xfc\xa7\
+\x00\x64\
+\x00\x6f\x00\x77\x00\x6e\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x1b\
+\x03\x5a\x32\x27\
+\x00\x63\
+\x00\x6f\x00\x6d\x00\x62\x00\x6f\x00\x62\x00\x6f\x00\x78\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\
+\x00\x73\x00\x61\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x17\
+\x0c\x65\xce\x07\
+\x00\x6c\
+\x00\x65\x00\x66\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x64\x00\x69\x00\x73\x00\x61\x00\x62\x00\x6c\
+\x00\x65\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x11\
+\x01\x1f\xc3\x87\
+\x00\x64\
+\x00\x6f\x00\x77\x00\x6e\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\
+\x00\x12\
+\x05\x8f\x9d\x07\
+\x00\x62\
+\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x6f\x00\x70\x00\x65\x00\x6e\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\
+\x00\x67\
+\x00\x12\
+\x03\x8d\x04\x47\
+\x00\x72\
+\x00\x69\x00\x67\x00\x68\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\
+\x00\x67\
\x00\x0e\
\x0e\xde\xfa\xc7\
\x00\x6c\
\x00\x65\x00\x66\x00\x74\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\x00\x0f\
-\x06\x53\x25\xa7\
+\x00\x14\
+\x04\x5e\x2d\xa7\
\x00\x62\
-\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x6f\x00\x70\x00\x65\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x72\x00\x61\x00\x6e\x00\x63\x00\x68\x00\x5f\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x64\x00\x5f\x00\x6f\x00\x6e\x00\x2e\
+\x00\x70\x00\x6e\x00\x67\
+\x00\x0c\
+\x06\xe6\xe6\x67\
+\x00\x75\
+\x00\x70\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x0f\
+\x01\x73\x8b\x07\
+\x00\x75\
+\x00\x70\x00\x5f\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x5f\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
"
qt_resource_struct_v1 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
-\x00\x00\x00\x16\x00\x02\x00\x00\x00\x13\x00\x00\x00\x03\
-\x00\x00\x02\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x1f\x3c\
-\x00\x00\x02\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x9d\
-\x00\x00\x01\xb0\x00\x00\x00\x00\x00\x01\x00\x00\x13\x68\
-\x00\x00\x01\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x12\x1d\
+\x00\x00\x00\x16\x00\x02\x00\x00\x00\x14\x00\x00\x00\x03\
+\x00\x00\x01\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x10\xb3\
+\x00\x00\x02\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x15\x93\
+\x00\x00\x01\x36\x00\x00\x00\x00\x00\x01\x00\x00\x11\x5d\
+\x00\x00\x03\x54\x00\x00\x00\x00\x00\x01\x00\x00\x27\x41\
+\x00\x00\x01\x60\x00\x00\x00\x00\x00\x01\x00\x00\x12\x07\
+\x00\x00\x00\x82\x00\x00\x00\x00\x00\x01\x00\x00\x07\xae\
+\x00\x00\x01\xfa\x00\x00\x00\x00\x00\x01\x00\x00\x14\x40\
+\x00\x00\x02\xbc\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x70\
+\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x07\x0a\
+\x00\x00\x03\x08\x00\x00\x00\x00\x00\x01\x00\x00\x1e\xbe\
+\x00\x00\x01\xd8\x00\x00\x00\x00\x00\x01\x00\x00\x13\x97\
+\x00\x00\x02\x92\x00\x00\x00\x00\x00\x01\x00\x00\x16\x3c\
\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x02\xb6\x00\x00\x00\x00\x00\x01\x00\x00\x1e\x92\
-\x00\x00\x00\x76\x00\x00\x00\x00\x00\x01\x00\x00\x07\xd8\
-\x00\x00\x01\x10\x00\x00\x00\x00\x00\x01\x00\x00\x10\xd6\
-\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x08\x81\
-\x00\x00\x01\xda\x00\x00\x00\x00\x00\x01\x00\x00\x14\x12\
-\x00\x00\x01\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x12\xbf\
-\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa4\
-\x00\x00\x03\x30\x00\x00\x00\x00\x00\x01\x00\x00\x20\x90\
-\x00\x00\x02\x98\x00\x00\x00\x00\x00\x01\x00\x00\x1d\xf0\
-\x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x09\x25\
-\x00\x00\x02\x64\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x46\
-\x00\x00\x02\x08\x00\x00\x00\x00\x00\x01\x00\x00\x1b\xf3\
-\x00\x00\x03\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x1f\xe6\
-\x00\x00\x01\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x11\x7a\
+\x00\x00\x03\x36\x00\x00\x00\x00\x00\x01\x00\x00\x26\x9f\
+\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x08\x58\
+\x00\x00\x02\x36\x00\x00\x00\x00\x00\x01\x00\x00\x14\xe9\
+\x00\x00\x00\xda\x00\x00\x00\x00\x00\x01\x00\x00\x10\x09\
+\x00\x00\x01\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x13\x4e\
+\x00\x00\x02\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x1e\x14\
+\x00\x00\x01\x84\x00\x00\x00\x00\x00\x01\x00\x00\x12\xab\
"
qt_resource_struct_v2 = b"\
@@ -816,49 +828,50 @@ qt_resource_struct_v2 = b"\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x16\x00\x02\x00\x00\x00\x13\x00\x00\x00\x03\
+\x00\x00\x00\x16\x00\x02\x00\x00\x00\x14\x00\x00\x00\x03\
\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x02\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x1f\x3c\
-\x00\x00\x01\x76\x41\x9d\xa2\x35\
-\x00\x00\x02\x3c\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x9d\
-\x00\x00\x01\x76\x41\x9d\xa2\x35\
-\x00\x00\x01\xb0\x00\x00\x00\x00\x00\x01\x00\x00\x13\x68\
-\x00\x00\x01\x79\xb4\x72\xcc\x9c\
-\x00\x00\x01\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x12\x1d\
-\x00\x00\x01\x76\x41\x9d\xa2\x39\
+\x00\x00\x01\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x10\xb3\
+\x00\x00\x01\x79\xec\x37\x3f\xbc\
+\x00\x00\x02\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x15\x93\
+\x00\x00\x01\x79\xec\x37\x3f\xba\
+\x00\x00\x01\x36\x00\x00\x00\x00\x00\x01\x00\x00\x11\x5d\
+\x00\x00\x01\x79\xec\x37\x3f\xb6\
+\x00\x00\x03\x54\x00\x00\x00\x00\x00\x01\x00\x00\x27\x41\
+\x00\x00\x01\x79\xec\x37\x3f\xc0\
+\x00\x00\x01\x60\x00\x00\x00\x00\x00\x01\x00\x00\x12\x07\
+\x00\x00\x01\x79\xec\x37\x3f\xbc\
+\x00\x00\x00\x82\x00\x00\x00\x00\x00\x01\x00\x00\x07\xae\
+\x00\x00\x01\x79\xec\x37\x3f\xb7\
+\x00\x00\x01\xfa\x00\x00\x00\x00\x00\x01\x00\x00\x14\x40\
+\x00\x00\x01\x79\xec\x37\x3f\xb7\
+\x00\x00\x02\xbc\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x70\
+\x00\x00\x01\x79\xec\x37\x3f\xbe\
+\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x07\x0a\
+\x00\x00\x01\x79\xec\x37\x3f\xbd\
+\x00\x00\x03\x08\x00\x00\x00\x00\x00\x01\x00\x00\x1e\xbe\
+\x00\x00\x01\x79\xec\x37\x3f\xb4\
+\x00\x00\x01\xd8\x00\x00\x00\x00\x00\x01\x00\x00\x13\x97\
+\x00\x00\x01\x79\xec\x37\x3f\xb8\
+\x00\x00\x02\x92\x00\x00\x00\x00\x00\x01\x00\x00\x16\x3c\
+\x00\x00\x01\x79\xec\x37\x3f\xb5\
\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x01\x76\x41\x9d\xa2\x37\
-\x00\x00\x02\xb6\x00\x00\x00\x00\x00\x01\x00\x00\x1e\x92\
-\x00\x00\x01\x79\xb4\x72\xcc\x9c\
-\x00\x00\x00\x76\x00\x00\x00\x00\x00\x01\x00\x00\x07\xd8\
-\x00\x00\x01\x79\xb4\x72\xcc\x9c\
-\x00\x00\x01\x10\x00\x00\x00\x00\x00\x01\x00\x00\x10\xd6\
-\x00\x00\x01\x76\x41\x9d\xa2\x37\
-\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x08\x81\
-\x00\x00\x01\x76\x41\x9d\xa2\x37\
-\x00\x00\x01\xda\x00\x00\x00\x00\x00\x01\x00\x00\x14\x12\
-\x00\x00\x01\x79\xc2\x05\x2b\x60\
-\x00\x00\x01\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x12\xbf\
-\x00\x00\x01\x76\x41\x9d\xa2\x35\
-\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa4\
-\x00\x00\x01\x79\xc1\xfc\x16\x91\
-\x00\x00\x03\x30\x00\x00\x00\x00\x00\x01\x00\x00\x20\x90\
-\x00\x00\x01\x79\xc1\xf9\x4b\x78\
-\x00\x00\x02\x98\x00\x00\x00\x00\x00\x01\x00\x00\x1d\xf0\
-\x00\x00\x01\x76\x41\x9d\xa2\x39\
-\x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x09\x25\
-\x00\x00\x01\x79\xc2\x05\x91\x2a\
-\x00\x00\x02\x64\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x46\
-\x00\x00\x01\x76\x41\x9d\xa2\x35\
-\x00\x00\x02\x08\x00\x00\x00\x00\x00\x01\x00\x00\x1b\xf3\
-\x00\x00\x01\x76\x41\x9d\xa2\x35\
-\x00\x00\x03\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x1f\xe6\
-\x00\x00\x01\x76\x41\x9d\xa2\x35\
-\x00\x00\x01\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x11\x7a\
-\x00\x00\x01\x76\x41\x9d\xa2\x39\
+\x00\x00\x01\x79\xec\x37\x3f\xb5\
+\x00\x00\x03\x36\x00\x00\x00\x00\x00\x01\x00\x00\x26\x9f\
+\x00\x00\x01\x79\xec\x37\x3f\xbe\
+\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x08\x58\
+\x00\x00\x01\x79\xec\x37\x3f\xb3\
+\x00\x00\x02\x36\x00\x00\x00\x00\x00\x01\x00\x00\x14\xe9\
+\x00\x00\x01\x79\xec\x37\x3f\xbb\
+\x00\x00\x00\xda\x00\x00\x00\x00\x00\x01\x00\x00\x10\x09\
+\x00\x00\x01\x79\xec\x37\x3f\xb9\
+\x00\x00\x01\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x13\x4e\
+\x00\x00\x01\x7c\xa7\x41\xfc\x00\
+\x00\x00\x02\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x1e\x14\
+\x00\x00\x01\x79\xec\x37\x3f\xbb\
+\x00\x00\x01\x84\x00\x00\x00\x00\x00\x01\x00\x00\x12\xab\
+\x00\x00\x01\x79\xec\x37\x3f\xbf\
"
-
qt_version = [int(v) for v in QtCore.qVersion().split('.')]
if qt_version < [5, 8, 0]:
rcc_version = 1
diff --git a/openpype/style/pyside2_resources.py b/openpype/style/pyside2_resources.py
index ee68a74b8e..dff01eec49 100644
--- a/openpype/style/pyside2_resources.py
+++ b/openpype/style/pyside2_resources.py
@@ -1,75 +1,15 @@
-# Resource object code (Python 3)
-# Created by: object code
-# Created by: The Resource Compiler for Qt version 5.15.2
+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created: Fri Oct 22 11:42:52 2021
+# by: The Resource Compiler for PySide2 (Qt v5.6.1)
+#
# WARNING! All changes made in this file will be lost!
from PySide2 import QtCore
-
qt_resource_data = b"\
-\x00\x00\x00\x9f\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x14\x1f\xf9\
-#\xd9\x0b\x00\x00\x00#IDAT\x08\xd7c`\xc0\
-\x0d\xe6|\x80\xb1\x18\x91\x05R\x04\xe0B\x08\x15)\x02\
-\x0c\x0c\x8c\xc8\x02\x08\x95h\x00\x00\xac\xac\x07\x90Ne\
-4\xac\x00\x00\x00\x00IEND\xaeB`\x82\
-\x00\x00\x00\xa6\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc\
-;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\
-\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\
-\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\
-\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEN\
-D\xaeB`\x82\
-\x00\x00\x00\xa5\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\
-\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\
-\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a\
-200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\
-\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\
-\xaeB`\x82\
-\x00\x00\x00\xa5\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\
-\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\
-\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a\
-200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\
-\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\
-\xaeB`\x82\
-\x00\x00\x00\xa0\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1f\x0d\xfc\
-R+\x9c\x00\x00\x00$IDAT\x08\xd7c`@\
-\x05s>\xc0XL\xc8\x5c&dY&d\xc5pN\
-\x8a\x00\x9c\x93\x22\x80a\x1a\x0a\x00\x00)\x95\x08\xaf\x88\
-\xac\xba4\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x00\xa6\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
@@ -83,31 +23,33 @@ HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
d``b``4D\xe2 s\x19\x90\x8d@\x02\
\x00d@\x09u\x86\xb3\xad\x9c\x00\x00\x00\x00IEN\
D\xaeB`\x82\
-\x00\x00\x00\x9e\
+\x00\x00\x00\xa5\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\
+\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a\
+200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\
+\xaeB`\x82\
+\x00\x00\x00\xa6\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15\x0f\xfd\
-\x8f\xf8.\x00\x00\x00\x22IDAT\x08\xd7c`\xc0\
-\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1BH*\x0c\x19\
-\x18\x18\x91\x05\x10*\xd1\x00\x00\xca\xb5\x07\xd2v\xbb\xb2\
-\xc5\x00\x00\x00\x00IEND\xaeB`\x82\
-\x00\x00\x00\x9e\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15\x0f\xfd\
-\x8f\xf8.\x00\x00\x00\x22IDAT\x08\xd7c`\xc0\
-\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1BH*\x0c\x19\
-\x18\x18\x91\x05\x10*\xd1\x00\x00\xca\xb5\x07\xd2v\xbb\xb2\
-\xc5\x00\x00\x00\x00IEND\xaeB`\x82\
-\x00\x00\x07\x06\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc\
+;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\
+\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x070\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x0a\x00\x00\x00\x07\x08\x06\x00\x00\x001\xac\xdcc\
@@ -165,10 +107,10 @@ toshop:ICCProfil\
e=\x22sRGB IEC61966\
-2.1\x22\x0a xmp:Mod\
ifyDate=\x222021-05\
--31T12:30:11+02:\
+-31T12:33:14+02:\
00\x22\x0a xmp:Metad\
ataDate=\x222021-05\
--31T12:30:11+02:\
+-31T12:33:14+02:\
00\x22>\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0a\x85\x9d\x9f\x08\x00\x00\x01\x83\
+nd=\x22r\x22?>H\x8b[^\x00\x00\x01\x83\
iCCPsRGB IEC6196\
6-2.1\x00\x00(\x91u\x91\xcf+DQ\x14\
\xc7?fh\xfc\x18\x8dba1e\x12\x16B\x83\x12\
@@ -213,28 +155,54 @@ S\xdc\xa1\xaa\xf0r\x0c\xf5\xb3\xd0x\x05\xb5\xf3\xc5\x9e\
\xfd\xecst\x07\xd15\xf9\xaaK\xd8\xd9\x85\x0e9\xef\
Y\xf8\x06\x8e\xfdg\xf8\xfd\x8a\x18\x97\x00\x00\x00\x09p\
HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00mIDAT\x18\x95u\xcf\xc1\x09\xc2P\
-\x10\x84\xe1\xd7\x85\x07\x9b\xd0C@\xd2\x82x\x14{0\
-W!\x8d\x84`?bKzH\xcc\x97\x83\xfb0\x04\
-\xdf\x9c\x86\x7fg\x99\xdd\x84\x0d\xaaT\x10jl\x13\x1e\
-\xbe\xba\xfe\x0951{\xe6\x8d\x0f&\x1c\x17\xa1S\xb0\
-\x11\x87\x0c/\x01\x07\xec\xb0\x0f?\xe1\xbc\xaei\xa3\xe6\
-\x85w\xf8[\xe9\xf0\xbb\x9f\xfa\xd2\x839\xdc\xa3[\xf3\
-\x19.\xa8\x89\xb50\xf7C\xa0\x00\x00\x00\x00IEN\
-D\xaeB`\x82\
-\x00\x00\x00\xa6\
+\x00\x00\x00\x97IDAT\x18\x95m\xcf\xb1j\x02A\
+\x14\x85\xe1o\xb7\xb6\xd0'H=Vi\x03\xb1\xb4H\
+;l\xa5\xf19\xf6Y\x02VB\xbaa\x0a\x0b;\x1b\
+\x1bkA\x18\x02)m\xe3\xbe\x82\xcd\x06\x16\xd9\xdb\xdd\
+\x9f\xff\x5c\xee\xa9b*\x13Ls\x13nF&\xa6\xf2\
+\x82\xaeF\x8b\xdf\x98\xca\xfb\x88\xb4\xc0\x0f\xda\x1a[t\
+\xd8\xc7T\xc2@\x9ac\x8f?|U=|\xc5\x09w\
+\xbc\xa1\xc2\x193,r\x13.\xd5\xe0\xc2\x12\x07\x5cQ\
+#\xe0#7\xe1\xa8O\x0e\x7f\xda`\xd7\xaf\x9f\xb9\x09\
+\xdfc\x05\xff\xe5uLe\xf5\xcc\x1f\x0d3,\x83\xb6\
+\x06D\x83\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\xa0\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1f \xb9\
-\x8dw\xe9\x00\x00\x00*IDAT\x08\xd7c`\xc0\
-\x06\xe6|```B0\xa1\x1c\x08\x93\x81\x81\x09\xc1\
-d``b`H\x11@\xe2 s\x19\x90\x8d@\x02\
-\x00#\xed\x08\xafd\x9f\x0f\x15\x00\x00\x00\x00IEN\
-D\xaeB`\x82\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1c\x1f$\
+\xc6\x09\x17\x00\x00\x00$IDAT\x08\xd7c`@\
+\x05\xff\xcf\xc3XL\xc8\x5c&dY&d\xc5p\x0e\
+\xa3!\x9c\xc3h\x88a\x1a\x0a\x00\x00m\x84\x09u7\
+\x9e\xd9#\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\x9e\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15\x0f\xfd\
+\x8f\xf8.\x00\x00\x00\x22IDAT\x08\xd7c`\xc0\
+\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1BH*\x0c\x19\
+\x18\x18\x91\x05\x10*\xd1\x00\x00\xca\xb5\x07\xd2v\xbb\xb2\
+\xc5\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\xa5\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\
+\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a\
+200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\
+\xaeB`\x82\
\x00\x00\x07\xdd\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
@@ -363,6 +331,221 @@ zpp\xf0\xe3\x0e.\xa4\xd2\xae\xf0\x8a\xf7\x9a\xe3V\
q[s\x5c@H\xa5\xdda\x81\x0d\x9ek\x8e\xff\xfd\
\xcf?\xcc1\xe9\x01\x1c\x00sR-q\xe4J\x1bi\
\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\x9e\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15\x0f\xfd\
+\x8f\xf8.\x00\x00\x00\x22IDAT\x08\xd7c`\xc0\
+\x0d\xfe\x9f\x87\xb1\x18\x91\x05\x18\x0d\xe1BH*\x0c\x19\
+\x18\x18\x91\x05\x10*\xd1\x00\x00\xca\xb5\x07\xd2v\xbb\xb2\
+\xc5\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\xa6\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc\
+;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\
+\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x00\xa6\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc\
+;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\
+\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\
+\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x00\xa5\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\
+\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\
+\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a\
+200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\
+\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\
+\xaeB`\x82\
+\x00\x00\x00\xa0\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1f\x0d\xfc\
+R+\x9c\x00\x00\x00$IDAT\x08\xd7c`@\
+\x05s>\xc0XL\xc8\x5c&dY&d\xc5pN\
+\x8a\x00\x9c\x93\x22\x80a\x1a\x0a\x00\x00)\x95\x08\xaf\x88\
+\xac\xba4\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x00\x9f\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x14\x1f\xf9\
+#\xd9\x0b\x00\x00\x00#IDAT\x08\xd7c`\xc0\
+\x0d\xe6|\x80\xb1\x18\x91\x05R\x04\xe0B\x08\x15)\x02\
+\x0c\x0c\x8c\xc8\x02\x08\x95h\x00\x00\xac\xac\x07\x90Ne\
+4\xac\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00\x07\x06\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x0a\x00\x00\x00\x07\x08\x06\x00\x00\x001\xac\xdcc\
+\x00\x00\x04\xb0iTXtXML:com.\
+adobe.xmp\x00\x00\x00\x00\x00\
+xpacket begin=\x22\xef\
+\xbb\xbf\x22 id=\x22W5M0MpCe\
+hiHzreSzNTczkc9d\
+\x22?>\x0a\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0a\x85\x9d\x9f\x08\x00\x00\x01\x83\
+iCCPsRGB IEC6196\
+6-2.1\x00\x00(\x91u\x91\xcf+DQ\x14\
+\xc7?fh\xfc\x18\x8dba1e\x12\x16B\x83\x12\
+\x1b\x8b\x99\x18\x0a\x8b\x99Q~mf\x9ey3j\xde\
+x\xbd7\xd2d\xabl\xa7(\xb1\xf1k\xc1_\xc0V\
+Y+E\xa4d\xa7\xac\x89\x0dz\xce\x9bQ#\x99s\
+;\xf7|\xee\xf7\xdes\xba\xf7\x5cpD\xd3\x8afV\
+\xfaA\xcbd\x8dp(\xe0\x9b\x99\x9d\xf3\xb9\x9e\xa8\xa2\
+\x85\x1a:\xf1\xc6\x14S\x9f\x8c\x8cF)k\xef\xb7T\
+\xd8\xf1\xba\xdb\xaeU\xfe\xdc\xbfV\xb7\x980\x15\xa8\xa8\
+\x16\x1eVt#+<&<\xb1\x9a\xd5m\xde\x12n\
+RR\xb1E\xe1\x13\xe1.C.(|c\xeb\xf1\x22\
+?\xdb\x9c,\xf2\xa7\xcdF4\x1c\x04G\x83\xb0/\xf9\
+\x8b\xe3\xbfXI\x19\x9a\xb0\xbc\x9c6-\xbd\xa2\xfc\xdc\
+\xc7~\x89;\x91\x99\x8eHl\x15\xf7b\x12&D\x00\
+\x1f\xe3\x8c\x10d\x80^\x86d\x1e\xa0\x9b>zdE\
+\x99|\x7f!\x7f\x8ae\xc9Ud\xd6\xc9a\xb0D\x92\
+\x14Y\xbaD]\x91\xea\x09\x89\xaa\xe8\x09\x19irv\
+\xff\xff\xf6\xd5T\xfb\xfb\x8a\xd5\xdd\x01\xa8z\xb4\xac\xd7\
+vpm\xc2W\xde\xb2>\x0e,\xeb\xeb\x10\x9c\x0fp\
+\x9e)\xe5/\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\x9eu\
+8\xbd(i\xf1m8\xdb\x80\xe6{=f\xc4\x0a\x92\
+S\xdc\xa1\xaa\xf0r\x0c\xf5\xb3\xd0x\x05\xb5\xf3\xc5\x9e\
+\xfd\xecst\x07\xd15\xf9\xaaK\xd8\xd9\x85\x0e9\xef\
+Y\xf8\x06\x8e\xfdg\xf8\xfd\x8a\x18\x97\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00mIDAT\x18\x95u\xcf\xc1\x09\xc2P\
+\x10\x84\xe1\xd7\x85\x07\x9b\xd0C@\xd2\x82x\x14{0\
+W!\x8d\x84`?bKzH\xcc\x97\x83\xfb0\x04\
+\xdf\x9c\x86\x7fg\x99\xdd\x84\x0d\xaaT\x10jl\x13\x1e\
+\xbe\xba\xfe\x0951{\xe6\x8d\x0f&\x1c\x17\xa1S\xb0\
+\x11\x87\x0c/\x01\x07\xec\xb0\x0f?\xe1\xbc\xaei\xa3\xe6\
+\x85w\xf8[\xe9\xf0\xbb\x9f\xfa\xd2\x839\xdc\xa3[\xf3\
+\x19.\xa8\x89\xb50\xf7C\xa0\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x00\xa6\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1f \xb9\
+\x8dw\xe9\x00\x00\x00*IDAT\x08\xd7c`\xc0\
+\x06\xe6|```B0\xa1\x1c\x08\x93\x81\x81\x09\xc1\
+d``b`H\x11@\xe2 s\x19\x90\x8d@\x02\
+\x00#\xed\x08\xafd\x9f\x0f\x15\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x00\xa0\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
+\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
+HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
+\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1c\x1f$\
+\xc6\x09\x17\x00\x00\x00$IDAT\x08\xd7c`@\
+\x05\xff\xcf\xc3XL\xc8\x5c&dY&d\xc5p\x0e\
+\xa3!\x9c\xc3h\x88a\x1a\x0a\x00\x00m\x84\x09u7\
+\x9e\xd9#\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x07\xad\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
@@ -501,186 +684,6 @@ HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
d``b``4D\xe2 s\x19\x90\x8d@\x02\
\x00d@\x09u\x86\xb3\xad\x9c\x00\x00\x00\x00IEN\
D\xaeB`\x82\
-\x00\x00\x00\xa5\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\x9cS4\xfc]\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x0b\x02\x04m\
-\x98\x1bi\x00\x00\x00)IDAT\x08\xd7c`\xc0\
-\x00\x8c\x0c\x0c\xff\xcf\xa3\x08\x18220 \x0b2\x1a\
-200B\x98\x10AFC\x14\x13P\xb5\xa3\x01\x00\
-\xd6\x10\x07\xd2/H\xdfJ\x00\x00\x00\x00IEND\
-\xaeB`\x82\
-\x00\x00\x00\xa0\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1c\x1f$\
-\xc6\x09\x17\x00\x00\x00$IDAT\x08\xd7c`@\
-\x05\xff\xcf\xc3XL\xc8\x5c&dY&d\xc5p\x0e\
-\xa3!\x9c\xc3h\x88a\x1a\x0a\x00\x00m\x84\x09u7\
-\x9e\xd9#\x00\x00\x00\x00IEND\xaeB`\x82\
-\x00\x00\x070\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x0a\x00\x00\x00\x07\x08\x06\x00\x00\x001\xac\xdcc\
-\x00\x00\x04\xb0iTXtXML:com.\
-adobe.xmp\x00\x00\x00\x00\x00\
-xpacket begin=\x22\xef\
-\xbb\xbf\x22 id=\x22W5M0MpCe\
-hiHzreSzNTczkc9d\
-\x22?>\x0a\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0aH\x8b[^\x00\x00\x01\x83\
-iCCPsRGB IEC6196\
-6-2.1\x00\x00(\x91u\x91\xcf+DQ\x14\
-\xc7?fh\xfc\x18\x8dba1e\x12\x16B\x83\x12\
-\x1b\x8b\x99\x18\x0a\x8b\x99Q~mf\x9ey3j\xde\
-x\xbd7\xd2d\xabl\xa7(\xb1\xf1k\xc1_\xc0V\
-Y+E\xa4d\xa7\xac\x89\x0dz\xce\x9bQ#\x99s\
-;\xf7|\xee\xf7\xdes\xba\xf7\x5cpD\xd3\x8afV\
-\xfaA\xcbd\x8dp(\xe0\x9b\x99\x9d\xf3\xb9\x9e\xa8\xa2\
-\x85\x1a:\xf1\xc6\x14S\x9f\x8c\x8cF)k\xef\xb7T\
-\xd8\xf1\xba\xdb\xaeU\xfe\xdc\xbfV\xb7\x980\x15\xa8\xa8\
-\x16\x1eVt#+<&<\xb1\x9a\xd5m\xde\x12n\
-RR\xb1E\xe1\x13\xe1.C.(|c\xeb\xf1\x22\
-?\xdb\x9c,\xf2\xa7\xcdF4\x1c\x04G\x83\xb0/\xf9\
-\x8b\xe3\xbfXI\x19\x9a\xb0\xbc\x9c6-\xbd\xa2\xfc\xdc\
-\xc7~\x89;\x91\x99\x8eHl\x15\xf7b\x12&D\x00\
-\x1f\xe3\x8c\x10d\x80^\x86d\x1e\xa0\x9b>zdE\
-\x99|\x7f!\x7f\x8ae\xc9Ud\xd6\xc9a\xb0D\x92\
-\x14Y\xbaD]\x91\xea\x09\x89\xaa\xe8\x09\x19irv\
-\xff\xff\xf6\xd5T\xfb\xfb\x8a\xd5\xdd\x01\xa8z\xb4\xac\xd7\
-vpm\xc2W\xde\xb2>\x0e,\xeb\xeb\x10\x9c\x0fp\
-\x9e)\xe5/\xef\xc3\xe0\x9b\xe8\xf9\x92\xd6\xb6\x07\x9eu\
-8\xbd(i\xf1m8\xdb\x80\xe6{=f\xc4\x0a\x92\
-S\xdc\xa1\xaa\xf0r\x0c\xf5\xb3\xd0x\x05\xb5\xf3\xc5\x9e\
-\xfd\xecst\x07\xd15\xf9\xaaK\xd8\xd9\x85\x0e9\xef\
-Y\xf8\x06\x8e\xfdg\xf8\xfd\x8a\x18\x97\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x97IDAT\x18\x95m\xcf\xb1j\x02A\
-\x14\x85\xe1o\xb7\xb6\xd0'H=Vi\x03\xb1\xb4H\
-;l\xa5\xf19\xf6Y\x02VB\xbaa\x0a\x0b;\x1b\
-\x1bkA\x18\x02)m\xe3\xbe\x82\xcd\x06\x16\xd9\xdb\xdd\
-\x9f\xff\x5c\xee\xa9b*\x13Ls\x13nF&\xa6\xf2\
-\x82\xaeF\x8b\xdf\x98\xca\xfb\x88\xb4\xc0\x0f\xda\x1a[t\
-\xd8\xc7T\xc2@\x9ac\x8f?|U=|\xc5\x09w\
-\xbc\xa1\xc2\x193,r\x13.\xd5\xe0\xc2\x12\x07\x5cQ\
-#\xe0#7\xe1\xa8O\x0e\x7f\xda`\xd7\xaf\x9f\xb9\x09\
-\xdfc\x05\xff\xe5uLe\xf5\xcc\x1f\x0d3,\x83\xb6\
-\x06D\x83\x00\x00\x00\x00IEND\xaeB`\x82\
-\x00\x00\x00\xa6\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc\
-;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\
-\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\
-\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\
-\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEN\
-D\xaeB`\x82\
-\x00\x00\x00\xa0\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x06\x00\x00\x00\x09\x08\x04\x00\x00\x00\xbb\x93\x95\x16\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x14\x1c\x1f$\
-\xc6\x09\x17\x00\x00\x00$IDAT\x08\xd7c`@\
-\x05\xff\xcf\xc3XL\xc8\x5c&dY&d\xc5p\x0e\
-\xa3!\x9c\xc3h\x88a\x1a\x0a\x00\x00m\x84\x09u7\
-\x9e\xd9#\x00\x00\x00\x00IEND\xaeB`\x82\
-\x00\x00\x00\xa6\
-\x89\
-PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
-\x00\x00\x09\x00\x00\x00\x06\x08\x04\x00\x00\x00\xbb\xce|N\
-\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x00\x09p\
-HYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\
-\x00\x00\x00\x07tIME\x07\xdc\x08\x17\x08\x15;\xdc\
-;\x0c\x9b\x00\x00\x00*IDAT\x08\xd7c`\xc0\
-\x00\x8c\x0c\x0cs> \x0b\xa4\x08020 \x0b\xa6\
-\x08000B\x98\x10\xc1\x14\x01\x14\x13P\xb5\xa3\x01\
-\x00\xc6\xb9\x07\x90]f\x1f\x83\x00\x00\x00\x00IEN\
-D\xaeB`\x82\
"
qt_resource_name = b"\
@@ -692,62 +695,6 @@ qt_resource_name = b"\
\x07\x03}\xc3\
\x00i\
\x00m\x00a\x00g\x00e\x00s\
-\x00\x15\
-\x0f\xf3\xc0\x07\
-\x00u\
-\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\
-\x00.\x00p\x00n\x00g\
-\x00\x12\
-\x01.\x03'\
-\x00c\
-\x00o\x00m\x00b\x00o\x00b\x00o\x00x\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\
-\x00g\
-\x00\x0e\
-\x04\xa2\xfc\xa7\
-\x00d\
-\x00o\x00w\x00n\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\
-\x00\x1b\
-\x03Z2'\
-\x00c\
-\x00o\x00m\x00b\x00o\x00b\x00o\x00x\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\
-\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\
-\x00\x18\
-\x03\x8e\xdeg\
-\x00r\
-\x00i\x00g\x00h\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\
-\x00l\x00e\x00d\x00.\x00p\x00n\x00g\
-\x00\x11\
-\x00\xb8\x8c\x07\
-\x00l\
-\x00e\x00f\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\x00.\x00p\x00n\x00g\
-\
-\x00\x0f\
-\x01s\x8b\x07\
-\x00u\
-\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\x00.\x00p\x00n\x00g\
-\x00\x0c\
-\x06\xe6\xe6g\
-\x00u\
-\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\
-\x00\x0f\
-\x06S%\xa7\
-\x00b\
-\x00r\x00a\x00n\x00c\x00h\x00_\x00o\x00p\x00e\x00n\x00.\x00p\x00n\x00g\
-\x00\x17\
-\x0ce\xce\x07\
-\x00l\
-\x00e\x00f\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\
-\x00e\x00d\x00.\x00p\x00n\x00g\
-\x00\x14\
-\x04^-\xa7\
-\x00b\
-\x00r\x00a\x00n\x00c\x00h\x00_\x00c\x00l\x00o\x00s\x00e\x00d\x00_\x00o\x00n\x00.\
-\x00p\x00n\x00g\
-\x00\x11\
-\x0b\xda0\xa7\
-\x00b\
-\x00r\x00a\x00n\x00c\x00h\x00_\x00c\x00l\x00o\x00s\x00e\x00d\x00.\x00p\x00n\x00g\
-\
\x00\x0e\
\x0e\xde\xfa\xc7\
\x00l\
@@ -757,87 +704,121 @@ qt_resource_name = b"\
\x00d\
\x00o\x00w\x00n\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\x00.\x00p\x00n\x00g\
\
-\x00\x0f\
-\x02\x9f\x05\x87\
-\x00r\
-\x00i\x00g\x00h\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\
+\x00\x12\
+\x01.\x03'\
+\x00c\
+\x00o\x00m\x00b\x00o\x00b\x00o\x00x\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\
+\x00g\
\x00\x12\
\x05\x8f\x9d\x07\
\x00b\
\x00r\x00a\x00n\x00c\x00h\x00_\x00o\x00p\x00e\x00n\x00_\x00o\x00n\x00.\x00p\x00n\
\x00g\
-\x00\x17\
-\x0c\xabQ\x07\
-\x00d\
-\x00o\x00w\x00n\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\
-\x00e\x00d\x00.\x00p\x00n\x00g\
\x00\x12\
\x03\x8d\x04G\
\x00r\
\x00i\x00g\x00h\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\x00.\x00p\x00n\
\x00g\
+\x00\x0f\
+\x01s\x8b\x07\
+\x00u\
+\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\x00.\x00p\x00n\x00g\
+\x00\x1b\
+\x03Z2'\
+\x00c\
+\x00o\x00m\x00b\x00o\x00b\x00o\x00x\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\
+\x00s\x00a\x00b\x00l\x00e\x00d\x00.\x00p\x00n\x00g\
+\x00\x14\
+\x04^-\xa7\
+\x00b\
+\x00r\x00a\x00n\x00c\x00h\x00_\x00c\x00l\x00o\x00s\x00e\x00d\x00_\x00o\x00n\x00.\
+\x00p\x00n\x00g\
+\x00\x0c\
+\x06\xe6\xe6g\
+\x00u\
+\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\
+\x00\x17\
+\x0c\xabQ\x07\
+\x00d\
+\x00o\x00w\x00n\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\
+\x00e\x00d\x00.\x00p\x00n\x00g\
\x00\x15\
\x03'rg\
\x00c\
\x00o\x00m\x00b\x00o\x00b\x00o\x00x\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\
\x00.\x00p\x00n\x00g\
+\x00\x0e\
+\x04\xa2\xfc\xa7\
+\x00d\
+\x00o\x00w\x00n\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\
+\x00\x18\
+\x03\x8e\xdeg\
+\x00r\
+\x00i\x00g\x00h\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\
+\x00l\x00e\x00d\x00.\x00p\x00n\x00g\
+\x00\x15\
+\x0f\xf3\xc0\x07\
+\x00u\
+\x00p\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\x00e\x00d\
+\x00.\x00p\x00n\x00g\
+\x00\x0f\
+\x06S%\xa7\
+\x00b\
+\x00r\x00a\x00n\x00c\x00h\x00_\x00o\x00p\x00e\x00n\x00.\x00p\x00n\x00g\
+\x00\x17\
+\x0ce\xce\x07\
+\x00l\
+\x00e\x00f\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00d\x00i\x00s\x00a\x00b\x00l\
+\x00e\x00d\x00.\x00p\x00n\x00g\
+\x00\x0f\
+\x02\x9f\x05\x87\
+\x00r\
+\x00i\x00g\x00h\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00.\x00p\x00n\x00g\
+\x00\x11\
+\x0b\xda0\xa7\
+\x00b\
+\x00r\x00a\x00n\x00c\x00h\x00_\x00c\x00l\x00o\x00s\x00e\x00d\x00.\x00p\x00n\x00g\
+\
+\x00\x11\
+\x00\xb8\x8c\x07\
+\x00l\
+\x00e\x00f\x00t\x00_\x00a\x00r\x00r\x00o\x00w\x00_\x00o\x00n\x00.\x00p\x00n\x00g\
+\
"
qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
-\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
-\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x16\x00\x02\x00\x00\x00\x13\x00\x00\x00\x03\
-\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x01\x16\x00\x00\x00\x00\x00\x01\x00\x00\x03C\
-\x00\x00\x01vA\x9d\xa25\
-\x00\x00\x02P\x00\x00\x00\x00\x00\x01\x00\x00\x1d!\
-\x00\x00\x01vA\x9d\xa25\
-\x00\x00\x00X\x00\x00\x00\x00\x00\x01\x00\x00\x00\xa3\
-\x00\x00\x01y\xb4r\xcc\x9c\
-\x00\x00\x01>\x00\x00\x00\x00\x00\x01\x00\x00\x03\xed\
-\x00\x00\x01vA\x9d\xa29\
-\x00\x00\x02x\x00\x00\x00\x00\x00\x01\x00\x00\x1d\xca\
-\x00\x00\x01vA\x9d\xa27\
-\x00\x00\x03$\x00\x00\x00\x00\x00\x01\x00\x00&\xf0\
-\x00\x00\x01y\xb4r\xcc\x9c\
-\x00\x00\x00\xa4\x00\x00\x00\x00\x00\x01\x00\x00\x01\xf6\
-\x00\x00\x01y\xb4r\xcc\x9c\
-\x00\x00\x02\xfa\x00\x00\x00\x00\x00\x01\x00\x00&L\
-\x00\x00\x01vA\x9d\xa27\
-\x00\x00\x00\xe0\x00\x00\x00\x00\x00\x01\x00\x00\x02\x9f\
-\x00\x00\x01vA\x9d\xa27\
-\x00\x00\x01\xd8\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xe5\
-\x00\x00\x01y\xc2\x05+`\
-\x00\x00\x00\x82\x00\x00\x00\x00\x00\x01\x00\x00\x01M\
-\x00\x00\x01vA\x9d\xa25\
-\x00\x00\x02\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x1en\
-\x00\x00\x01y\xc1\xfc\x16\x91\
-\x00\x00\x01\x80\x00\x00\x00\x00\x00\x01\x00\x00\x051\
-\x00\x00\x01y\xc1\xf9Kx\
-\x00\x00\x01b\x00\x00\x00\x00\x00\x01\x00\x00\x04\x8f\
-\x00\x00\x01vA\x9d\xa29\
-\x00\x00\x02\x06\x00\x00\x00\x00\x00\x01\x00\x00\x14\xc6\
-\x00\x00\x01y\xc2\x05\x91*\
-\x00\x00\x01\xa4\x00\x00\x00\x00\x00\x01\x00\x00\x0c;\
-\x00\x00\x01vA\x9d\xa25\
-\x00\x00\x02\xc6\x00\x00\x00\x00\x00\x01\x00\x00%\xa2\
-\x00\x00\x01vA\x9d\xa25\
-\x00\x00\x02.\x00\x00\x00\x00\x00\x01\x00\x00\x1cw\
-\x00\x00\x01vA\x9d\xa25\
+\x00\x00\x03,\x00\x00\x00\x00\x00\x01\x00\x00&\xf0\
+\x00\x00\x00J\x00\x00\x00\x00\x00\x01\x00\x00\x00\xaa\
+\x00\x00\x00r\x00\x00\x00\x00\x00\x01\x00\x00\x01S\
+\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x01\x00\x00\x09\xd5\
+\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00\x1e\x9b\
+\x00\x00\x01\xd0\x00\x00\x00\x00\x00\x01\x00\x00\x14M\
+\x00\x00\x01\x14\x00\x00\x00\x00\x00\x01\x00\x00\x0aw\
+\x00\x00\x00\xc6\x00\x00\x00\x00\x00\x01\x00\x00\x091\
+\x00\x00\x02\x22\x00\x00\x00\x00\x00\x01\x00\x00\x15\xa0\
+\x00\x00\x01P\x00\x00\x00\x00\x00\x01\x00\x00\x0b \
+\x00\x00\x02\x00\x00\x00\x00\x00\x00\x01\x00\x00\x14\xf7\
+\x00\x00\x00\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x01\xfd\
+\x00\x00\x02\x88\x00\x00\x00\x00\x00\x01\x00\x00\x16\xe7\
+\x00\x00\x01~\x00\x00\x00\x00\x00\x01\x00\x00\x13\x01\
+\x00\x00\x03\x04\x00\x00\x00\x00\x00\x01\x00\x00\x1f?\
+\x00\x00\x02\xac\x00\x00\x00\x00\x00\x01\x00\x00\x1d\xf1\
+\x00\x00\x01\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x13\xa3\
\x00\x00\x00(\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x01vA\x9d\xa29\
+\x00\x00\x02X\x00\x00\x00\x00\x00\x01\x00\x00\x16D\
"
def qInitResources():
QtCore.qRegisterResourceData(
- 0x03, qt_resource_struct, qt_resource_name, qt_resource_data
+ 0x01, qt_resource_struct, qt_resource_name, qt_resource_data
)
def qCleanupResources():
QtCore.qUnregisterResourceData(
- 0x03, qt_resource_struct, qt_resource_name, qt_resource_data
+ 0x01, qt_resource_struct, qt_resource_name, qt_resource_data
)
diff --git a/openpype/style/resources.qrc b/openpype/style/resources.qrc
index a583d9458e..e2e69711f4 100644
--- a/openpype/style/resources.qrc
+++ b/openpype/style/resources.qrc
@@ -19,5 +19,6 @@
images/up_arrow.png
images/up_arrow_disabled.png
images/up_arrow_on.png
+ images/transparent.png
diff --git a/openpype/style/style.css b/openpype/style/style.css
index d9b8ca2869..066455a7d4 100644
--- a/openpype/style/style.css
+++ b/openpype/style/style.css
@@ -206,12 +206,28 @@ QComboBox::down-arrow, QComboBox::down-arrow:on, QComboBox::down-arrow:hover, QC
}
/* Splitter */
-QSplitter {
- border: none;
+QSplitter::handle {
+ border: 3px solid transparent;
}
-QSplitter::handle {
- border: 1px dotted {color:bg-menu-separator};
+QSplitter::handle:horizontal {
+ /* must be single like because of Nuke*/
+ background: qlineargradient(x1:0, y1:0, x2:1, y2:0,stop:0.3 rgba(0, 0, 0, 0),stop:0.5 {color:bg-splitter},stop:0.7 rgba(0, 0, 0, 0));
+}
+
+QSplitter::handle:vertical {
+ /* must be single like because of Nuke*/
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0.3 rgba(0, 0, 0, 0),stop:0.5 {color:bg-splitter},stop:0.7 rgba(0, 0, 0, 0));
+}
+
+QSplitter::handle:horizontal:hover {
+ /* must be single like because of Nuke*/
+ background: qlineargradient(x1:0, y1:0, x2:1, y2:0,stop:0.3 rgba(0, 0, 0, 0),stop:0.5 {color:bg-splitter-hover},stop:0.7 rgba(0, 0, 0, 0));
+}
+
+QSplitter::handle:vertical:hover {
+ /* must be single like because of Nuke*/
+ background: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0.3 rgba(0, 0, 0, 0),stop:0.5 {color:bg-splitter-hover},stop:0.7 rgba(0, 0, 0, 0));
}
/* SLider */
@@ -238,18 +254,15 @@ QSlider::groove:focus {
border-color: {color:border-focus};
}
QSlider::handle {
- background: qlineargradient(
- x1: 0, y1: 0.5,
- x2: 1, y2: 0.5,
- stop: 0 {palette:blue-base},
- stop: 1 {palette:green-base}
- );
+ /* must be single like because of Nuke*/
+ background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5,stop: 0 {palette:blue-base},stop: 1 {palette:green-base});
border: 1px solid #5c5c5c;
width: 10px;
height: 10px;
border-radius: 5px;
}
+
QSlider::handle:horizontal {
margin: -2px 0;
}
@@ -258,12 +271,8 @@ QSlider::handle:vertical {
}
QSlider::handle:disabled {
- background: qlineargradient(
- x1:0, y1:0,
- x2:1, y2:1,
- stop:0 {color:bg-buttons},
- stop:1 {color:bg-buttons-disabled}
- );
+ /* must be single like because of Nuke*/
+ background: qlineargradient(x1:0, y1:0,x2:1, y2:1,stop:0 {color:bg-buttons},stop:1 {color:bg-buttons-disabled});
}
/* Tab widget*/
@@ -281,19 +290,15 @@ QTabBar::tab {
border-left: 3px solid transparent;
border-top: 1px solid {color:border};
border-right: 1px solid {color:border};
- background: qlineargradient(
- x1: 0, y1: 1, x2: 0, y2: 0,
- stop: 0.5 {color:bg}, stop: 1.0 {color:bg-inputs}
- );
+ /* must be single like because of Nuke*/
+ background: qlineargradient(x1: 0, y1: 1, x2: 0, y2: 0,stop: 0.5 {color:bg}, stop: 1.0 {color:bg-inputs});
}
QTabBar::tab:selected {
background: {color:grey-lighter};
border-left: 3px solid {color:border-focus};
- background: qlineargradient(
- x1: 0, y1: 1, x2: 0, y2: 0,
- stop: 0.5 {color:bg}, stop: 1.0 {color:border}
- );
+ /* must be single like because of Nuke*/
+ background: qlineargradient(x1: 0, y1: 1, x2: 0, y2: 0,stop: 0.5 {color:bg}, stop: 1.0 {color:border});
}
QTabBar::tab:!selected {
@@ -341,6 +346,15 @@ QHeaderView::section:first {
QHeaderView::section:last {
border-right: none;
}
+
+QHeaderView::down-arrow {
+ image: url(:/openpype/images/down_arrow.png);
+}
+
+QHeaderView::up-arrow {
+ image: url(:/openpype/images/up_arrow.png);
+}
+
/* Views QListView QTreeView QTableView */
QAbstractItemView {
border: 0px solid {color:border};
@@ -399,23 +413,42 @@ QAbstractItemView::branch:open:has-children:has-siblings {
QAbstractItemView::branch:open:has-children:!has-siblings:hover,
QAbstractItemView::branch:open:has-children:has-siblings:hover {
border-image: none;
- image: url(:/openpype/images//branch_open_on.png);
+ image: url(:/openpype/images/branch_open_on.png);
background: transparent;
}
QAbstractItemView::branch:has-children:!has-siblings:closed,
QAbstractItemView::branch:closed:has-children:has-siblings {
border-image: none;
- image: url(:/openpype/images//branch_closed.png);
+ image: url(:/openpype/images/branch_closed.png);
background: transparent;
}
QAbstractItemView::branch:has-children:!has-siblings:closed:hover,
QAbstractItemView::branch:closed:has-children:has-siblings:hover {
border-image: none;
- image: url(:/openpype/images//branch_closed_on.png);
+ image: url(:/openpype/images/branch_closed_on.png);
background: transparent;
}
+QAbstractItemView::branch:has-siblings:!adjoins-item {
+ border-image: none;
+ image: url(:/openpype/images/transparent.png);
+ background: transparent;
+}
+
+QAbstractItemView::branch:has-siblings:adjoins-item {
+ border-image: none;
+ image: url(:/openpype/images/transparent.png);
+ background: transparent;
+}
+
+QAbstractItemView::branch:!has-children:!has-siblings:adjoins-item {
+ border-image: none;
+ image: url(:/openpype/images/transparent.png);
+ background: transparent;
+}
+
+
/* Progress bar */
QProgressBar {
border: 1px solid {color:border};
@@ -431,12 +464,8 @@ QProgressBar:vertical {
}
QProgressBar::chunk {
- background: qlineargradient(
- x1: 0, y1: 0.5,
- x2: 1, y2: 0.5,
- stop: 0 {palette:blue-base},
- stop: 1 {palette:green-base}
- );
+ /* must be single like because of Nuke*/
+ background: qlineargradient(x1: 0, y1: 0.5,x2: 1, y2: 0.5,stop: 0 {palette:blue-base},stop: 1 {palette:green-base});
}
/* Scroll bars */
@@ -645,6 +674,19 @@ QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
font-family: "Roboto Mono";
}
+#SubsetView::item, #RepresentationView:item {
+ padding: 5px 1px;
+ border: 0px;
+}
+
+#OptionalActionBody, #OptionalActionOption {
+ background: transparent;
+}
+
+#OptionalActionBody[state="hover"], #OptionalActionOption[state="hover"] {
+ background: {color:bg-view-hover};
+}
+
/* New Create/Publish UI */
#PublishLogConsole {
font-family: "Roboto Mono";
diff --git a/openpype/tools/experimental_tools/__init__.py b/openpype/tools/experimental_tools/__init__.py
index 75e3210aab..d6315e4655 100644
--- a/openpype/tools/experimental_tools/__init__.py
+++ b/openpype/tools/experimental_tools/__init__.py
@@ -3,12 +3,12 @@ from .tools_def import (
LOCAL_EXPERIMENTAL_KEY
)
-from .dialog import ExperimentalDialog
+from .dialog import ExperimentalToolsDialog
__all__ = (
"ExperimentalTools",
"LOCAL_EXPERIMENTAL_KEY",
- "ExperimentalDialog"
+ "ExperimentalToolsDialog"
)
diff --git a/openpype/tools/experimental_tools/dialog.py b/openpype/tools/experimental_tools/dialog.py
index a611416efc..72503a1aff 100644
--- a/openpype/tools/experimental_tools/dialog.py
+++ b/openpype/tools/experimental_tools/dialog.py
@@ -21,16 +21,17 @@ class ToolButton(QtWidgets.QPushButton):
self.triggered.emit(self._identifier)
-class ExperimentalDialog(QtWidgets.QDialog):
+class ExperimentalToolsDialog(QtWidgets.QDialog):
refresh_interval = 3000
def __init__(self, parent=None):
- super(ExperimentalDialog, self).__init__(parent)
+ super(ExperimentalToolsDialog, self).__init__(parent)
self.setWindowTitle("OpenPype Experimental tools")
icon = QtGui.QIcon(app_icon_path())
self.setWindowIcon(icon)
self.setStyleSheet(load_stylesheet())
+ # Widgets for cases there are not available experimental tools
empty_widget = QtWidgets.QWidget(self)
empty_label = QtWidgets.QLabel(
@@ -50,16 +51,42 @@ class ExperimentalDialog(QtWidgets.QDialog):
empty_layout.addStretch(1)
empty_layout.addLayout(empty_btns_layout)
- content_widget = QtWidgets.QWidget(self)
+ # Content of Experimental tools
- content_layout = QtWidgets.QVBoxLayout(content_widget)
+ # Layout where buttons are added
+ content_layout = QtWidgets.QVBoxLayout()
content_layout.setContentsMargins(0, 0, 0, 0)
+ # Separator line
+ separator_widget = QtWidgets.QWidget(self)
+ separator_widget.setObjectName("Separator")
+ separator_widget.setMinimumHeight(2)
+ separator_widget.setMaximumHeight(2)
+
+ # Label describing how to turn off tools
+ tool_btns_widget = QtWidgets.QWidget(self)
+ tool_btns_label = QtWidgets.QLabel(
+ (
+ "You can enable these features in"
+ "
OpenPype tray -> Settings -> Experimental tools"
+ ),
+ tool_btns_widget
+ )
+ tool_btns_label.setAlignment(QtCore.Qt.AlignCenter)
+
+ tool_btns_layout = QtWidgets.QVBoxLayout(tool_btns_widget)
+ tool_btns_layout.setContentsMargins(0, 0, 0, 0)
+ tool_btns_layout.addLayout(content_layout)
+ tool_btns_layout.addStretch(1)
+ tool_btns_layout.addWidget(separator_widget, 0)
+ tool_btns_layout.addWidget(tool_btns_label, 0)
+
experimental_tools = ExperimentalTools()
+ # Main layout
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(empty_widget, 1)
- layout.addWidget(content_widget, 1)
+ layout.addWidget(tool_btns_widget, 1)
refresh_timer = QtCore.QTimer()
refresh_timer.setInterval(self.refresh_interval)
@@ -68,7 +95,7 @@ class ExperimentalDialog(QtWidgets.QDialog):
ok_btn.clicked.connect(self._on_ok_click)
self._empty_widget = empty_widget
- self._content_widget = content_widget
+ self._tool_btns_widget = tool_btns_widget
self._content_layout = content_layout
self._experimental_tools = experimental_tools
@@ -95,7 +122,7 @@ class ExperimentalDialog(QtWidgets.QDialog):
button = self._buttons_by_tool_identifier[identifier]
else:
is_new = True
- button = ToolButton(identifier, self)
+ button = ToolButton(identifier, self._tool_btns_widget)
button.triggered.connect(self._on_btn_trigger)
self._buttons_by_tool_identifier[identifier] = button
self._content_layout.insertWidget(idx, button)
@@ -112,6 +139,9 @@ class ExperimentalDialog(QtWidgets.QDialog):
"\n\nOpenPype Tray > Settings > Experimental Tools"
))
+ if tool.enabled != button.isEnabled():
+ button.setEnabled(tool.enabled)
+
for identifier in buttons_to_remove:
button = self._buttons_by_tool_identifier.pop(identifier)
button.setVisible(False)
@@ -126,7 +156,7 @@ class ExperimentalDialog(QtWidgets.QDialog):
def _set_visibility(self):
content_visible = self._is_content_visible()
- self._content_widget.setVisible(content_visible)
+ self._tool_btns_widget.setVisible(content_visible)
self._empty_widget.setVisible(not content_visible)
def _on_ok_click(self):
@@ -138,7 +168,7 @@ class ExperimentalDialog(QtWidgets.QDialog):
tool.execute()
def showEvent(self, event):
- super(ExperimentalDialog, self).showEvent(event)
+ super(ExperimentalToolsDialog, self).showEvent(event)
if self._refresh_on_active:
# Start/Restart timer
@@ -151,6 +181,8 @@ class ExperimentalDialog(QtWidgets.QDialog):
if self._first_show:
self._first_show = False
+ # Set stylesheet
+ self.setStyleSheet(load_stylesheet())
# Resize dialog if there is not content
if not self._is_content_visible():
size = self.size()
@@ -164,7 +196,7 @@ class ExperimentalDialog(QtWidgets.QDialog):
self._refresh_timer.start()
self.refresh()
- super(ExperimentalDialog, self).changeEvent(event)
+ super(ExperimentalToolsDialog, self).changeEvent(event)
def _on_refresh_timeout(self):
# Stop timer if window is not visible
diff --git a/openpype/tools/experimental_tools/tools_def.py b/openpype/tools/experimental_tools/tools_def.py
index ef6b004b50..63116c72c4 100644
--- a/openpype/tools/experimental_tools/tools_def.py
+++ b/openpype/tools/experimental_tools/tools_def.py
@@ -8,6 +8,8 @@ LOCAL_EXPERIMENTAL_KEY = "experimental_tools"
class ExperimentalTool:
"""Definition of experimental tool.
+ Definition is used in local settings and in experimental tools dialog.
+
Args:
identifier (str): String identifier of tool (unique).
label (str): Label shown in UI.
@@ -69,6 +71,20 @@ class ExperimentalTools:
"Combined creation and publishing into one tool."
)
]
+
+ # --- Example tool (callback will just print on click) ---
+ # def example_callback(*args):
+ # print("Triggered tool")
+ #
+ # experimental_tools = [
+ # ExperimentalTool(
+ # "example",
+ # "Example experimental tool",
+ # example_callback,
+ # "Example tool tooltip."
+ # )
+ # ]
+
# Try to get host name from env variable `AVALON_APP`
if not host_name:
host_name = os.environ.get("AVALON_APP")
@@ -97,13 +113,32 @@ class ExperimentalTools:
).format(tool.identifier))
tools_by_identifier[tool.identifier] = tool
- self.tools_by_identifier = tools_by_identifier
- self.tools = experimental_tools
+ self._tools_by_identifier = tools_by_identifier
+ self._tools = experimental_tools
self._parent_widget = parent
- self._publisher_tool = None
+ @property
+ def tools(self):
+ """Tools in list.
+
+ Returns:
+ list: Tools filtered by host name if filtering was enabled
+ on initialization.
+ """
+ return self._tools
+
+ @property
+ def tools_by_identifier(self):
+ """Tools by their identifier.
+
+ Returns:
+ dict: Tools by identifier filtered by host name if filtering
+ was enabled on initialization.
+ """
+ return self._tools_by_identifier
def refresh_availability(self):
+ """Reload local settings and check if any tool changed ability."""
local_settings = get_local_settings()
experimental_settings = (
local_settings.get(LOCAL_EXPERIMENTAL_KEY)
diff --git a/openpype/tools/libraryloader/app.py b/openpype/tools/libraryloader/app.py
index 8080c547c9..d7c6c162e6 100644
--- a/openpype/tools/libraryloader/app.py
+++ b/openpype/tools/libraryloader/app.py
@@ -2,8 +2,8 @@ import sys
from Qt import QtWidgets, QtCore, QtGui
-from avalon import style
from avalon.api import AvalonMongoDB
+from openpype import style
from openpype.tools.utils import lib as tools_lib
from openpype.tools.loader.widgets import (
ThumbnailWidget,
@@ -28,152 +28,182 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
tool_title = "Library Loader 0.5"
tool_name = "library_loader"
+ message_timeout = 5000
+
def __init__(
self, parent=None, icon=None, show_projects=False, show_libraries=True
):
super(LibraryLoaderWindow, self).__init__(parent)
+ # Window modifications
+ self.setWindowTitle(self.tool_title)
+ window_flags = QtCore.Qt.Window
+ if not parent:
+ window_flags |= QtCore.Qt.WindowStaysOnTopHint
+ self.setWindowFlags(window_flags)
+ self.setFocusPolicy(QtCore.Qt.StrongFocus)
+
+ icon = QtGui.QIcon(style.app_icon_path())
+ self.setWindowIcon(icon)
+
+ self._first_show = True
self._initial_refresh = False
self._ignore_project_change = False
- # Enable minimize and maximize for app
- self.setWindowTitle(self.tool_title)
- self.setWindowFlags(QtCore.Qt.Window)
- self.setFocusPolicy(QtCore.Qt.StrongFocus)
- if icon is not None:
- self.setWindowIcon(icon)
- # self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
+ dbcon = AvalonMongoDB()
+ dbcon.install()
+ dbcon.Session["AVALON_PROJECT"] = None
- body = QtWidgets.QWidget()
- footer = QtWidgets.QWidget()
- footer.setFixedHeight(20)
-
- container = QtWidgets.QWidget()
-
- self.dbcon = AvalonMongoDB()
- self.dbcon.install()
- self.dbcon.Session["AVALON_PROJECT"] = None
+ self.dbcon = dbcon
self.show_projects = show_projects
self.show_libraries = show_libraries
# Groups config
- self.groups_config = tools_lib.GroupsConfig(self.dbcon)
- self.family_config_cache = tools_lib.FamilyConfigCache(self.dbcon)
+ self.groups_config = tools_lib.GroupsConfig(dbcon)
+ self.family_config_cache = tools_lib.FamilyConfigCache(dbcon)
- assets = AssetWidget(
- self.dbcon, multiselection=True, parent=self
+ # UI initialization
+ main_splitter = QtWidgets.QSplitter(self)
+
+ # --- Left part ---
+ left_side_splitter = QtWidgets.QSplitter(main_splitter)
+ left_side_splitter.setOrientation(QtCore.Qt.Vertical)
+
+ # Project combobox
+ projects_combobox = QtWidgets.QComboBox(left_side_splitter)
+ combobox_delegate = QtWidgets.QStyledItemDelegate(self)
+ projects_combobox.setItemDelegate(combobox_delegate)
+
+ # Assets widget
+ assets_widget = AssetWidget(
+ dbcon, multiselection=True, parent=left_side_splitter
)
- families = FamilyListView(
- self.dbcon, self.family_config_cache, parent=self
+
+ # Families widget
+ families_filter_view = FamilyListView(
+ dbcon, self.family_config_cache, left_side_splitter
)
- subsets = LibrarySubsetWidget(
- self.dbcon,
+ left_side_splitter.addWidget(projects_combobox)
+ left_side_splitter.addWidget(assets_widget)
+ left_side_splitter.addWidget(families_filter_view)
+ left_side_splitter.setStretchFactor(1, 65)
+ left_side_splitter.setStretchFactor(2, 35)
+
+ # --- Middle part ---
+ # Subsets widget
+ subsets_widget = LibrarySubsetWidget(
+ dbcon,
self.groups_config,
self.family_config_cache,
tool_name=self.tool_name,
parent=self
)
- version = VersionWidget(self.dbcon)
- thumbnail = ThumbnailWidget(self.dbcon)
-
- # Project
- self.combo_projects = QtWidgets.QComboBox()
-
- # Create splitter to show / hide family filters
- asset_filter_splitter = QtWidgets.QSplitter()
- asset_filter_splitter.setOrientation(QtCore.Qt.Vertical)
- asset_filter_splitter.addWidget(self.combo_projects)
- asset_filter_splitter.addWidget(assets)
- asset_filter_splitter.addWidget(families)
- asset_filter_splitter.setStretchFactor(1, 65)
- asset_filter_splitter.setStretchFactor(2, 35)
-
- manager = ModulesManager()
- sync_server = manager.modules_by_name["sync_server"]
-
- representations = RepresentationWidget(self.dbcon)
- thumb_ver_splitter = QtWidgets.QSplitter()
+ # --- Right part ---
+ thumb_ver_splitter = QtWidgets.QSplitter(main_splitter)
thumb_ver_splitter.setOrientation(QtCore.Qt.Vertical)
- thumb_ver_splitter.addWidget(thumbnail)
- thumb_ver_splitter.addWidget(version)
- if sync_server.enabled:
- thumb_ver_splitter.addWidget(representations)
+
+ thumbnail_widget = ThumbnailWidget(dbcon, parent=thumb_ver_splitter)
+ version_info_widget = VersionWidget(dbcon, parent=thumb_ver_splitter)
+
+ thumb_ver_splitter.addWidget(thumbnail_widget)
+ thumb_ver_splitter.addWidget(version_info_widget)
+
thumb_ver_splitter.setStretchFactor(0, 30)
thumb_ver_splitter.setStretchFactor(1, 35)
- container_layout = QtWidgets.QHBoxLayout(container)
- container_layout.setContentsMargins(0, 0, 0, 0)
- split = QtWidgets.QSplitter()
- split.addWidget(asset_filter_splitter)
- split.addWidget(subsets)
- split.addWidget(thumb_ver_splitter)
- split.setSizes([180, 950, 200])
- container_layout.addWidget(split)
+ manager = ModulesManager()
+ sync_server = manager.modules_by_name.get("sync_server")
+ sync_server_enabled = False
+ if sync_server is not None:
+ sync_server_enabled = sync_server.enabled
- body_layout = QtWidgets.QHBoxLayout(body)
- body_layout.addWidget(container)
- body_layout.setContentsMargins(0, 0, 0, 0)
+ repres_widget = None
+ if sync_server_enabled:
+ repres_widget = RepresentationWidget(
+ dbcon, self.tool_name, parent=thumb_ver_splitter
+ )
+ thumb_ver_splitter.addWidget(repres_widget)
- message = QtWidgets.QLabel()
- message.hide()
+ main_splitter.addWidget(left_side_splitter)
+ main_splitter.addWidget(subsets_widget)
+ main_splitter.addWidget(thumb_ver_splitter)
+ if sync_server_enabled:
+ main_splitter.setSizes([250, 1000, 550])
+ else:
+ main_splitter.setSizes([250, 850, 200])
- footer_layout = QtWidgets.QVBoxLayout(footer)
- footer_layout.addWidget(message)
+ # --- Footer ---
+ footer_widget = QtWidgets.QWidget(self)
+ footer_widget.setFixedHeight(20)
+
+ message_label = QtWidgets.QLabel(footer_widget)
+
+ footer_layout = QtWidgets.QVBoxLayout(footer_widget)
footer_layout.setContentsMargins(0, 0, 0, 0)
+ footer_layout.addWidget(message_label)
layout = QtWidgets.QVBoxLayout(self)
- layout.addWidget(body)
- layout.addWidget(footer)
+ layout.addWidget(main_splitter)
+ layout.addWidget(footer_widget)
self.data = {
- "widgets": {
- "families": families,
- "assets": assets,
- "subsets": subsets,
- "version": version,
- "thumbnail": thumbnail,
- "representations": representations
- },
- "label": {
- "message": message,
- },
"state": {
"assetIds": None
}
}
- families.active_changed.connect(subsets.set_family_filters)
- assets.selection_changed.connect(self.on_assetschanged)
- assets.refresh_triggered.connect(self.on_assetschanged)
- assets.view.clicked.connect(self.on_assetview_click)
- subsets.active_changed.connect(self.on_subsetschanged)
- subsets.version_changed.connect(self.on_versionschanged)
- subsets.refreshed.connect(self._on_subset_refresh)
- self.combo_projects.currentTextChanged.connect(self.on_project_change)
+ message_timer = QtCore.QTimer()
+ message_timer.setInterval(self.message_timeout)
+ message_timer.setSingleShot(True)
+
+ message_timer.timeout.connect(self._on_message_timeout)
+
+ families_filter_view.active_changed.connect(
+ self._on_family_filter_change
+ )
+ assets_widget.selection_changed.connect(self.on_assetschanged)
+ assets_widget.refresh_triggered.connect(self.on_assetschanged)
+ assets_widget.view.clicked.connect(self.on_assetview_click)
+ subsets_widget.active_changed.connect(self.on_subsetschanged)
+ subsets_widget.version_changed.connect(self.on_versionschanged)
+ subsets_widget.refreshed.connect(self._on_subset_refresh)
+ projects_combobox.currentTextChanged.connect(self.on_project_change)
self.sync_server = sync_server
+ self._sync_server_enabled = sync_server_enabled
- # Set default thumbnail on start
- thumbnail.set_thumbnail(None)
+ self._combobox_delegate = combobox_delegate
+ self._projects_combobox = projects_combobox
+ self._assets_widget = assets_widget
+ self._families_filter_view = families_filter_view
- # Defaults
- if sync_server.enabled:
- split.setSizes([250, 1000, 550])
- self.resize(1800, 900)
- else:
- split.setSizes([250, 850, 200])
- self.resize(1300, 700)
+ self._subsets_widget = subsets_widget
+
+ self._version_info_widget = version_info_widget
+ self._thumbnail_widget = thumbnail_widget
+ self._repres_widget = repres_widget
+
+ self._message_label = message_label
+ self._message_timer = message_timer
def showEvent(self, event):
super(LibraryLoaderWindow, self).showEvent(event)
+ if self._first_show:
+ self._first_show = False
+ self.setStyleSheet(style.load_stylesheet())
+ if self._sync_server_enabled:
+ self.resize(1800, 900)
+ else:
+ self.resize(1300, 700)
+
if not self._initial_refresh:
+ self._initial_refresh = True
self.refresh()
def on_assetview_click(self, *args):
- subsets_widget = self.data["widgets"]["subsets"]
- selection_model = subsets_widget.view.selectionModel()
+ selection_model = self._subsets_widget.view.selectionModel()
if selection_model.selectedIndexes():
selection_model.clearSelection()
@@ -184,7 +214,7 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
self._ignore_project_change = True
# Cleanup
- self.combo_projects.clear()
+ self._projects_combobox.clear()
# Fill combobox with projects
select_project_item = QtGui.QStandardItem("< Select project >")
@@ -199,18 +229,18 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
item.setData(project_name, QtCore.Qt.UserRole + 1)
combobox_items.append(item)
- root_item = self.combo_projects.model().invisibleRootItem()
+ root_item = self._projects_combobox.model().invisibleRootItem()
root_item.appendRows(combobox_items)
index = 0
self._ignore_project_change = False
if old_project_name:
- index = self.combo_projects.findText(
+ index = self._projects_combobox.findText(
old_project_name, QtCore.Qt.MatchFixedString
)
- self.combo_projects.setCurrentIndex(index)
+ self._projects_combobox.setCurrentIndex(index)
def get_filtered_projects(self):
projects = list()
@@ -228,8 +258,8 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
if self._ignore_project_change:
return
- row = self.combo_projects.currentIndex()
- index = self.combo_projects.model().index(row, 0)
+ row = self._projects_combobox.currentIndex()
+ index = self._projects_combobox.model().index(row, 0)
project_name = index.data(QtCore.Qt.UserRole + 1)
self.dbcon.Session["AVALON_PROJECT"] = project_name
@@ -242,11 +272,9 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
"Config `%s` has no function `install`" % _config.__name__
)
- subsets = self.data["widgets"]["subsets"]
- representations = self.data["widgets"]["representations"]
-
- subsets.on_project_change(self.dbcon.Session["AVALON_PROJECT"])
- representations.on_project_change(self.dbcon.Session["AVALON_PROJECT"])
+ self._subsets_widget.on_project_change(project_name)
+ if self._repres_widget:
+ self._repres_widget.on_project_change(project_name)
self.family_config_cache.refresh()
self.groups_config.refresh()
@@ -260,13 +288,7 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
@property
def current_project(self):
- if (
- not self.dbcon.active_project() or
- self.dbcon.active_project() == ""
- ):
- return None
-
- return self.dbcon.active_project()
+ return self.dbcon.active_project() or None
# -------------------------------
# Delay calling blocking methods
@@ -289,12 +311,11 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
tools_lib.schedule(self._versionschanged, 150, channel="mongo")
def _on_subset_refresh(self, has_item):
- subsets_widget = self.data["widgets"]["subsets"]
- families_view = self.data["widgets"]["families"]
-
- subsets_widget.set_loading_state(loading=False, empty=not has_item)
- families = subsets_widget.get_subsets_families()
- families_view.set_enabled_families(families)
+ self._subsets_widget.set_loading_state(
+ loading=False, empty=not has_item
+ )
+ families = self._subsets_widget.get_subsets_families()
+ self._families_filter_view.set_enabled_families(families)
def set_context(self, context, refresh=True):
self.echo("Setting context: {}".format(context))
@@ -304,6 +325,9 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
)
# ------------------------------
+ def _on_family_filter_change(self, families):
+ self._subsets_widget.set_family_filters(families)
+
def _refresh(self):
if not self._initial_refresh:
self._initial_refresh = True
@@ -319,74 +343,69 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
)
assert project_doc, "This is a bug"
- assets_widget = self.data["widgets"]["assets"]
- families_view = self.data["widgets"]["families"]
- families_view.set_enabled_families(set())
- families_view.refresh()
+ self._families_filter_view.set_enabled_families(set())
+ self._families_filter_view.refresh()
- assets_widget.model.stop_fetch_thread()
- assets_widget.refresh()
- assets_widget.setFocus()
+ self._assets_widget.model.stop_fetch_thread()
+ self._assets_widget.refresh()
+ self._assets_widget.setFocus()
def clear_assets_underlines(self):
last_asset_ids = self.data["state"]["assetIds"]
if not last_asset_ids:
return
- assets_widget = self.data["widgets"]["assets"]
- id_role = assets_widget.model.ObjectIdRole
+ assets_model = self._assets_widget.model
+ id_role = assets_model.ObjectIdRole
- for index in tools_lib.iter_model_rows(assets_widget.model, 0):
+ for index in tools_lib.iter_model_rows(assets_model, 0):
if index.data(id_role) not in last_asset_ids:
continue
- assets_widget.model.setData(
- index, [], assets_widget.model.subsetColorsRole
+ assets_model.setData(
+ index, [], assets_model.subsetColorsRole
)
def _assetschanged(self):
"""Selected assets have changed"""
- assets_widget = self.data["widgets"]["assets"]
- subsets_widget = self.data["widgets"]["subsets"]
- subsets_model = subsets_widget.model
+ subsets_model = self._subsets_widget.model
subsets_model.clear()
self.clear_assets_underlines()
if not self.dbcon.Session.get("AVALON_PROJECT"):
- subsets_widget.set_loading_state(
+ self._subsets_widget.set_loading_state(
loading=False,
empty=True
)
return
# filter None docs they are silo
- asset_docs = assets_widget.get_selected_assets()
+ asset_docs = self._assets_widget.get_selected_assets()
if len(asset_docs) == 0:
return
asset_ids = [asset_doc["_id"] for asset_doc in asset_docs]
# Start loading
- subsets_widget.set_loading_state(
+ self._subsets_widget.set_loading_state(
loading=bool(asset_ids),
empty=True
)
subsets_model.set_assets(asset_ids)
- subsets_widget.view.setColumnHidden(
+ self._subsets_widget.view.setColumnHidden(
subsets_model.Columns.index("asset"),
len(asset_ids) < 2
)
# Clear the version information on asset change
- self.data["widgets"]["version"].set_version(None)
- self.data["widgets"]["thumbnail"].set_thumbnail(asset_docs)
+ self._version_info_widget.set_version(None)
+ self._thumbnail_widget.set_thumbnail(asset_docs)
self.data["state"]["assetIds"] = asset_ids
- representations = self.data["widgets"]["representations"]
# reset repre list
- representations.set_version_ids([])
+ self._repres_widget.set_version_ids([])
def _subsetschanged(self):
asset_ids = self.data["state"]["assetIds"]
@@ -395,8 +414,9 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
self._versionschanged()
return
- subsets = self.data["widgets"]["subsets"]
- selected_subsets = subsets.selected_subsets(_merged=True, _other=False)
+ selected_subsets = self._subsets_widget.selected_subsets(
+ _merged=True, _other=False
+ )
asset_models = {}
asset_ids = []
@@ -417,26 +437,24 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
self.clear_assets_underlines()
- assets_widget = self.data["widgets"]["assets"]
- indexes = assets_widget.view.selectionModel().selectedRows()
+ indexes = self._assets_widget.view.selectionModel().selectedRows()
+ assets_model = self._assets_widget.model
for index in indexes:
- id = index.data(assets_widget.model.ObjectIdRole)
+ id = index.data(assets_model.ObjectIdRole)
if id not in asset_models:
continue
- assets_widget.model.setData(
- index, asset_models[id], assets_widget.model.subsetColorsRole
+ assets_model.setData(
+ index, asset_models[id], assets_model.subsetColorsRole
)
# Trigger repaint
- assets_widget.view.updateGeometries()
+ self._assets_widget.view.updateGeometries()
# Set version in Version Widget
self._versionschanged()
def _versionschanged(self):
-
- subsets = self.data["widgets"]["subsets"]
- selection = subsets.view.selectionModel()
+ selection = self._subsets_widget.view.selectionModel()
# Active must be in the selected rows otherwise we
# assume it's not actually an "active" current index.
@@ -445,7 +463,7 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
active = selection.currentIndex()
rows = selection.selectedRows(column=active.column())
if active and active in rows:
- item = active.data(subsets.model.ItemRole)
+ item = active.data(self._subsets_widget.model.ItemRole)
if (
item is not None
and not (item.get("isGroup") or item.get("isMerged"))
@@ -457,7 +475,7 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
for index in rows:
if not index or not index.isValid():
continue
- item = index.data(subsets.model.ItemRole)
+ item = index.data(self._subsets_widget.model.ItemRole)
if (
item is None
or item.get("isGroup")
@@ -466,20 +484,18 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
continue
version_docs.append(item["version_document"])
- self.data["widgets"]["version"].set_version(version_doc)
+ self._version_info_widget.set_version(version_doc)
thumbnail_docs = version_docs
if not thumbnail_docs:
- assets_widget = self.data["widgets"]["assets"]
- asset_docs = assets_widget.get_selected_assets()
+ asset_docs = self._assets_widget.get_selected_assets()
if len(asset_docs) > 0:
thumbnail_docs = asset_docs
- self.data["widgets"]["thumbnail"].set_thumbnail(thumbnail_docs)
+ self._thumbnail_widget.set_thumbnail(thumbnail_docs)
- representations = self.data["widgets"]["representations"]
version_ids = [doc["_id"] for doc in version_docs or []]
- representations.set_version_ids(version_ids)
+ self._repres_widget.set_version_ids(version_ids)
def _set_context(self, context, refresh=True):
"""Set the selection in the interface using a context.
@@ -507,16 +523,15 @@ class LibraryLoaderWindow(QtWidgets.QDialog):
# scheduled refresh and the silo tabs are not shown.
self._refresh_assets()
- asset_widget = self.data["widgets"]["assets"]
- asset_widget.select_assets(asset)
+ self._assets_widget.select_assets(asset)
+
+ def _on_message_timeout(self):
+ self._message_label.setText("")
def echo(self, message):
- widget = self.data["label"]["message"]
- widget.setText(str(message))
- widget.show()
+ self._message_label.setText(str(message))
print(message)
-
- tools_lib.schedule(widget.hide, 5000, channel="message")
+ self._message_timer.start()
def closeEvent(self, event):
# Kill on holding SHIFT
@@ -573,7 +588,6 @@ def show(
window = LibraryLoaderWindow(
parent, icon, show_projects, show_libraries
)
- window.setStyleSheet(style.load_stylesheet())
window.show()
module.window = window
diff --git a/openpype/tools/loader/app.py b/openpype/tools/loader/app.py
index c18b6e798a..dac5e11d4c 100644
--- a/openpype/tools/loader/app.py
+++ b/openpype/tools/loader/app.py
@@ -1,10 +1,10 @@
import sys
from Qt import QtWidgets, QtCore
-from avalon import api, io, style, pipeline
+from avalon import api, io, pipeline
+from openpype import style
from openpype.tools.utils.widgets import AssetWidget
-
from openpype.tools.utils import lib
from .widgets import (
@@ -37,6 +37,7 @@ class LoaderWindow(QtWidgets.QDialog):
"""Asset loader interface"""
tool_name = "loader"
+ message_timeout = 5000
def __init__(self, parent=None):
super(LoaderWindow, self).__init__(parent)
@@ -51,86 +52,91 @@ class LoaderWindow(QtWidgets.QDialog):
self.family_config_cache = lib.FamilyConfigCache(io)
# Enable minimize and maximize for app
- self.setWindowFlags(QtCore.Qt.Window)
+ window_flags = QtCore.Qt.Window
+ if not parent:
+ window_flags |= QtCore.Qt.WindowStaysOnTopHint
+ self.setWindowFlags(window_flags)
self.setFocusPolicy(QtCore.Qt.StrongFocus)
- body = QtWidgets.QWidget()
- footer = QtWidgets.QWidget()
- footer.setFixedHeight(20)
+ main_splitter = QtWidgets.QSplitter(self)
- container = QtWidgets.QWidget()
+ # --- Left part ---
+ left_side_splitter = QtWidgets.QSplitter(main_splitter)
+ left_side_splitter.setOrientation(QtCore.Qt.Vertical)
- assets = AssetWidget(io, multiselection=True, parent=self)
- assets.set_current_asset_btn_visibility(True)
+ # Assets widget
+ assets_widget = AssetWidget(
+ io, multiselection=True, parent=left_side_splitter
+ )
+ assets_widget.set_current_asset_btn_visibility(True)
- families = FamilyListView(io, self.family_config_cache, self)
- subsets = SubsetWidget(
+ # Families widget
+ families_filter_view = FamilyListView(
+ io, self.family_config_cache, left_side_splitter
+ )
+ left_side_splitter.addWidget(assets_widget)
+ left_side_splitter.addWidget(families_filter_view)
+ left_side_splitter.setStretchFactor(0, 65)
+ left_side_splitter.setStretchFactor(1, 35)
+
+ # --- Middle part ---
+ # Subsets widget
+ subsets_widget = SubsetWidget(
io,
self.groups_config,
self.family_config_cache,
tool_name=self.tool_name,
- parent=self
+ parent=main_splitter
)
- version = VersionWidget(io)
- thumbnail = ThumbnailWidget(io)
- representations = RepresentationWidget(io, self.tool_name)
- manager = ModulesManager()
- sync_server = manager.modules_by_name["sync_server"]
-
- thumb_ver_splitter = QtWidgets.QSplitter()
+ # --- Right part ---
+ thumb_ver_splitter = QtWidgets.QSplitter(main_splitter)
thumb_ver_splitter.setOrientation(QtCore.Qt.Vertical)
- thumb_ver_splitter.addWidget(thumbnail)
- thumb_ver_splitter.addWidget(version)
- if sync_server.enabled:
- thumb_ver_splitter.addWidget(representations)
+
+ thumbnail_widget = ThumbnailWidget(io, parent=thumb_ver_splitter)
+ version_info_widget = VersionWidget(io, parent=thumb_ver_splitter)
+
+ thumb_ver_splitter.addWidget(thumbnail_widget)
+ thumb_ver_splitter.addWidget(version_info_widget)
+
thumb_ver_splitter.setStretchFactor(0, 30)
thumb_ver_splitter.setStretchFactor(1, 35)
- # Create splitter to show / hide family filters
- asset_filter_splitter = QtWidgets.QSplitter()
- asset_filter_splitter.setOrientation(QtCore.Qt.Vertical)
- asset_filter_splitter.addWidget(assets)
- asset_filter_splitter.addWidget(families)
- asset_filter_splitter.setStretchFactor(0, 65)
- asset_filter_splitter.setStretchFactor(1, 35)
+ manager = ModulesManager()
+ sync_server = manager.modules_by_name.get("sync_server")
+ sync_server_enabled = False
+ if sync_server is not None:
+ sync_server_enabled = sync_server.enabled
- container_layout = QtWidgets.QHBoxLayout(container)
- container_layout.setContentsMargins(0, 0, 0, 0)
- split = QtWidgets.QSplitter()
- split.addWidget(asset_filter_splitter)
- split.addWidget(subsets)
- split.addWidget(thumb_ver_splitter)
+ repres_widget = None
+ if sync_server_enabled:
+ repres_widget = RepresentationWidget(
+ io, self.tool_name, parent=thumb_ver_splitter
+ )
+ thumb_ver_splitter.addWidget(repres_widget)
- container_layout.addWidget(split)
+ main_splitter.addWidget(left_side_splitter)
+ main_splitter.addWidget(subsets_widget)
+ main_splitter.addWidget(thumb_ver_splitter)
- body_layout = QtWidgets.QHBoxLayout(body)
- body_layout.addWidget(container)
- body_layout.setContentsMargins(0, 0, 0, 0)
+ if sync_server_enabled:
+ main_splitter.setSizes([250, 1000, 550])
+ else:
+ main_splitter.setSizes([250, 850, 200])
- message = QtWidgets.QLabel()
- message.hide()
+ footer_widget = QtWidgets.QWidget(self)
- footer_layout = QtWidgets.QVBoxLayout(footer)
- footer_layout.addWidget(message)
+ message_label = QtWidgets.QLabel(footer_widget)
+
+ footer_layout = QtWidgets.QHBoxLayout(footer_widget)
footer_layout.setContentsMargins(0, 0, 0, 0)
+ footer_layout.addWidget(message_label, 1)
layout = QtWidgets.QVBoxLayout(self)
- layout.addWidget(body)
- layout.addWidget(footer)
+ layout.addWidget(main_splitter, 1)
+ layout.addWidget(footer_widget, 0)
self.data = {
- "widgets": {
- "families": families,
- "assets": assets,
- "subsets": subsets,
- "version": version,
- "thumbnail": thumbnail,
- "representations": representations
- },
- "label": {
- "message": message,
- },
"state": {
"assetIds": None
}
@@ -139,19 +145,43 @@ class LoaderWindow(QtWidgets.QDialog):
overlay_frame = OverlayFrame("Loading...", self)
overlay_frame.setVisible(False)
- families.active_changed.connect(subsets.set_family_filters)
- assets.selection_changed.connect(self.on_assetschanged)
- assets.refresh_triggered.connect(self.on_assetschanged)
- assets.view.clicked.connect(self.on_assetview_click)
- subsets.active_changed.connect(self.on_subsetschanged)
- subsets.version_changed.connect(self.on_versionschanged)
- subsets.refreshed.connect(self._on_subset_refresh)
+ message_timer = QtCore.QTimer()
+ message_timer.setInterval(self.message_timeout)
+ message_timer.setSingleShot(True)
- subsets.load_started.connect(self._on_load_start)
- subsets.load_ended.connect(self._on_load_end)
- representations.load_started.connect(self._on_load_start)
- representations.load_ended.connect(self._on_load_end)
+ message_timer.timeout.connect(self._on_message_timeout)
+ families_filter_view.active_changed.connect(
+ self._on_family_filter_change
+ )
+ assets_widget.selection_changed.connect(self.on_assetschanged)
+ assets_widget.refresh_triggered.connect(self.on_assetschanged)
+ # TODO do not touch view in asset widget
+ assets_widget.view.clicked.connect(self.on_assetview_click)
+ subsets_widget.active_changed.connect(self.on_subsetschanged)
+ subsets_widget.version_changed.connect(self.on_versionschanged)
+ subsets_widget.refreshed.connect(self._on_subset_refresh)
+
+ subsets_widget.load_started.connect(self._on_load_start)
+ subsets_widget.load_ended.connect(self._on_load_end)
+ repres_widget.load_started.connect(self._on_load_start)
+ repres_widget.load_ended.connect(self._on_load_end)
+
+ self._sync_server_enabled = sync_server_enabled
+
+ self._assets_widget = assets_widget
+ self._families_filter_view = families_filter_view
+
+ self._subsets_widget = subsets_widget
+
+ self._version_info_widget = version_info_widget
+ self._thumbnail_widget = thumbnail_widget
+ self._repres_widget = repres_widget
+
+ self._message_label = message_label
+ self._message_timer = message_timer
+
+ # TODO add overlay using stack widget
self._overlay_frame = overlay_frame
self.family_config_cache.refresh()
@@ -160,13 +190,7 @@ class LoaderWindow(QtWidgets.QDialog):
self._refresh()
self._assetschanged()
- # Defaults
- if sync_server.enabled:
- split.setSizes([250, 1000, 550])
- self.resize(1800, 900)
- else:
- split.setSizes([250, 850, 200])
- self.resize(1300, 700)
+ self._first_show = True
def resizeEvent(self, event):
super(LoaderWindow, self).resizeEvent(event)
@@ -176,13 +200,23 @@ class LoaderWindow(QtWidgets.QDialog):
super(LoaderWindow, self).moveEvent(event)
self._overlay_frame.move(0, 0)
+ def showEvent(self, event):
+ super(LoaderWindow, self).showEvent(event)
+ if self._first_show:
+ self._first_show = False
+ self.setStyleSheet(style.load_stylesheet())
+ if self._sync_server_enabled:
+ self.resize(1800, 900)
+ else:
+ self.resize(1300, 700)
+
# -------------------------------
# Delay calling blocking methods
# -------------------------------
def on_assetview_click(self, *args):
- subsets_widget = self.data["widgets"]["subsets"]
- selection_model = subsets_widget.view.selectionModel()
+ # TODO do not touch inner attributes of subset widget
+ selection_model = self._subsets_widget.view.selectionModel()
if selection_model.selectedIndexes():
selection_model.clearSelection()
@@ -216,12 +250,11 @@ class LoaderWindow(QtWidgets.QDialog):
self._overlay_frame.setVisible(False)
def _on_subset_refresh(self, has_item):
- subsets_widget = self.data["widgets"]["subsets"]
- families_view = self.data["widgets"]["families"]
-
- subsets_widget.set_loading_state(loading=False, empty=not has_item)
- families = subsets_widget.get_subsets_families()
- families_view.set_enabled_families(families)
+ self._subsets_widget.set_loading_state(
+ loading=False, empty=not has_item
+ )
+ families = self._subsets_widget.get_subsets_families()
+ self._families_filter_view.set_enabled_families(families)
def _on_load_end(self):
# Delay hiding as click events happened during loading should be
@@ -229,14 +262,14 @@ class LoaderWindow(QtWidgets.QDialog):
QtCore.QTimer.singleShot(100, self._hide_overlay)
# ------------------------------
+ def _on_family_filter_change(self, families):
+ self._subsets_widget.set_family_filters(families)
def on_context_task_change(self, *args, **kwargs):
- assets_widget = self.data["widgets"]["assets"]
- families_view = self.data["widgets"]["families"]
# Refresh families config
- families_view.refresh()
+ self._families_filter_view.refresh()
# Change to context asset on context change
- assets_widget.select_assets(io.Session["AVALON_ASSET"])
+ self._assets_widget.select_assets(io.Session["AVALON_ASSET"])
def _refresh(self):
"""Load assets from database"""
@@ -245,12 +278,10 @@ class LoaderWindow(QtWidgets.QDialog):
project = io.find_one({"type": "project"}, {"type": 1})
assert project, "Project was not found! This is a bug"
- assets_widget = self.data["widgets"]["assets"]
- assets_widget.refresh()
- assets_widget.setFocus()
+ self._assets_widget.refresh()
+ self._assets_widget.setFocus()
- families_view = self.data["widgets"]["families"]
- families_view.refresh()
+ self._families_filter_view.refresh()
def clear_assets_underlines(self):
"""Clear colors from asset data to remove colored underlines
@@ -258,11 +289,12 @@ class LoaderWindow(QtWidgets.QDialog):
own selected subsets. These colors must be cleared from asset data
on selection change so they match current selection.
"""
- last_asset_ids = self.data["state"]["assetIds"]
+ # TODO do not touch inner attributes of asset widget
+ last_asset_ids = self.data["state"]["assetIds"] or []
if not last_asset_ids:
return
- assets_widget = self.data["widgets"]["assets"]
+ assets_widget = self._assets_widget
id_role = assets_widget.model.ObjectIdRole
for index in lib.iter_model_rows(assets_widget.model, 0):
@@ -275,15 +307,15 @@ class LoaderWindow(QtWidgets.QDialog):
def _assetschanged(self):
"""Selected assets have changed"""
- assets_widget = self.data["widgets"]["assets"]
- subsets_widget = self.data["widgets"]["subsets"]
+ subsets_widget = self._subsets_widget
+ # TODO do not touch subset widget inner attributes
subsets_model = subsets_widget.model
subsets_model.clear()
self.clear_assets_underlines()
# filter None docs they are silo
- asset_docs = assets_widget.get_selected_assets()
+ asset_docs = self._assets_widget.get_selected_assets()
asset_ids = [asset_doc["_id"] for asset_doc in asset_docs]
# Start loading
@@ -299,14 +331,14 @@ class LoaderWindow(QtWidgets.QDialog):
)
# Clear the version information on asset change
- self.data["widgets"]["version"].set_version(None)
- self.data["widgets"]["thumbnail"].set_thumbnail(asset_docs)
+ self._thumbnail_widget.set_thumbnail(asset_docs)
+ self._version_info_widget.set_version(None)
self.data["state"]["assetIds"] = asset_ids
- representations = self.data["widgets"]["representations"]
# reset repre list
- representations.set_version_ids([])
+ if self._repres_widget is not None:
+ self._repres_widget.set_version_ids([])
def _subsetschanged(self):
asset_ids = self.data["state"]["assetIds"]
@@ -315,8 +347,9 @@ class LoaderWindow(QtWidgets.QDialog):
self._versionschanged()
return
- subsets = self.data["widgets"]["subsets"]
- selected_subsets = subsets.selected_subsets(_merged=True, _other=False)
+ selected_subsets = self._subsets_widget.selected_subsets(
+ _merged=True, _other=False
+ )
asset_models = {}
asset_ids = []
@@ -337,7 +370,8 @@ class LoaderWindow(QtWidgets.QDialog):
self.clear_assets_underlines()
- assets_widget = self.data["widgets"]["assets"]
+ # TODO do not use inner attributes of asset widget
+ assets_widget = self._assets_widget
indexes = assets_widget.view.selectionModel().selectedRows()
for index in indexes:
@@ -354,7 +388,7 @@ class LoaderWindow(QtWidgets.QDialog):
self._versionschanged()
def _versionschanged(self):
- subsets = self.data["widgets"]["subsets"]
+ subsets = self._subsets_widget
selection = subsets.view.selectionModel()
# Active must be in the selected rows otherwise we
@@ -386,23 +420,24 @@ class LoaderWindow(QtWidgets.QDialog):
else:
version_docs.append(item["version_document"])
- self.data["widgets"]["version"].set_version(version_doc)
+ self._version_info_widget.set_version(version_doc)
thumbnail_docs = version_docs
- assets_widget = self.data["widgets"]["assets"]
- asset_docs = assets_widget.get_selected_assets()
+ asset_docs = self._assets_widget.get_selected_assets()
if not thumbnail_docs:
if len(asset_docs) > 0:
thumbnail_docs = asset_docs
- self.data["widgets"]["thumbnail"].set_thumbnail(thumbnail_docs)
+ self._thumbnail_widget.set_thumbnail(thumbnail_docs)
- representations = self.data["widgets"]["representations"]
- version_ids = [doc["_id"] for doc in version_docs or []]
- representations.set_version_ids(version_ids)
+ if self._repres_widget is not None:
+ version_ids = [doc["_id"] for doc in version_docs or []]
+ self._repres_widget.set_version_ids(version_ids)
- # representations.change_visibility("subset", len(rows) > 1)
- # representations.change_visibility("asset", len(asset_docs) > 1)
+ # self._repres_widget.change_visibility("subset", len(rows) > 1)
+ # self._repres_widget.change_visibility(
+ # "asset", len(asset_docs) > 1
+ # )
def _set_context(self, context, refresh=True):
"""Set the selection in the interface using a context.
@@ -435,16 +470,15 @@ class LoaderWindow(QtWidgets.QDialog):
# scheduled refresh and the silo tabs are not shown.
self._refresh()
- asset_widget = self.data["widgets"]["assets"]
- asset_widget.select_assets(asset)
+ self._assets_widget.select_assets(asset)
+
+ def _on_message_timeout(self):
+ self._message_label.setText("")
def echo(self, message):
- widget = self.data["label"]["message"]
- widget.setText(str(message))
- widget.show()
+ self._message_label.setText(str(message))
print(message)
-
- lib.schedule(widget.hide, 5000, channel="message")
+ self._message_timer.start()
def closeEvent(self, event):
# Kill on holding SHIFT
@@ -472,7 +506,7 @@ class LoaderWindow(QtWidgets.QDialog):
event.setAccepted(True) # Avoid interfering other widgets
def show_grouping_dialog(self):
- subsets = self.data["widgets"]["subsets"]
+ subsets = self._subsets_widget
if not subsets.is_groupable():
self.echo("Grouping not enabled.")
return
@@ -511,7 +545,8 @@ class SubsetGroupingDialog(QtWidgets.QDialog):
self.items = items
self.groups_config = groups_config
- self.subsets = parent.data["widgets"]["subsets"]
+ # TODO do not touch inner attributes
+ self.subsets = parent._subsets_widget
self.asset_ids = parent.data["state"]["assetIds"]
name = QtWidgets.QLineEdit()
@@ -630,7 +665,6 @@ def show(debug=False, parent=None, use_context=False):
with lib.application():
window = LoaderWindow(parent)
- window.setStyleSheet(style.load_stylesheet())
window.show()
if use_context:
diff --git a/openpype/tools/loader/images/default_thumbnail.png b/openpype/tools/loader/images/default_thumbnail.png
index 97bd958e0d..adea862e5b 100644
Binary files a/openpype/tools/loader/images/default_thumbnail.png and b/openpype/tools/loader/images/default_thumbnail.png differ
diff --git a/openpype/tools/loader/widgets.py b/openpype/tools/loader/widgets.py
index 6b94fc6e44..4c075382ac 100644
--- a/openpype/tools/loader/widgets.py
+++ b/openpype/tools/loader/widgets.py
@@ -37,12 +37,13 @@ class OverlayFrame(QtWidgets.QFrame):
super(OverlayFrame, self).__init__(parent)
label_widget = QtWidgets.QLabel(label, self)
+ label_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground)
+
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.addWidget(label_widget, 1, QtCore.Qt.AlignCenter)
self.label_widget = label_widget
- label_widget.setStyleSheet("background: transparent;")
self.setStyleSheet((
"background: rgba(0, 0, 0, 127);"
"font-size: 60pt;"
@@ -159,36 +160,40 @@ class SubsetWidget(QtWidgets.QWidget):
grouping=enable_grouping
)
proxy = SubsetFilterProxyModel()
+ proxy.setSourceModel(model)
+ proxy.setDynamicSortFilter(True)
+ proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
+
family_proxy = FamiliesFilterProxyModel()
family_proxy.setSourceModel(proxy)
- subset_filter = QtWidgets.QLineEdit()
+ subset_filter = QtWidgets.QLineEdit(self)
subset_filter.setPlaceholderText("Filter subsets..")
- groupable = QtWidgets.QCheckBox("Enable Grouping")
- groupable.setChecked(enable_grouping)
+ group_checkbox = QtWidgets.QCheckBox("Enable Grouping", self)
+ group_checkbox.setChecked(enable_grouping)
top_bar_layout = QtWidgets.QHBoxLayout()
top_bar_layout.addWidget(subset_filter)
- top_bar_layout.addWidget(groupable)
+ top_bar_layout.addWidget(group_checkbox)
- view = TreeViewSpinner()
+ view = TreeViewSpinner(self)
+ view.setModel(family_proxy)
view.setObjectName("SubsetView")
view.setIndentation(20)
- view.setStyleSheet("""
- QTreeView::item{
- padding: 5px 1px;
- border: 0px;
- }
- """)
view.setAllColumnsShowFocus(True)
+ view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
+ view.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
+ view.setSortingEnabled(True)
+ view.sortByColumn(1, QtCore.Qt.AscendingOrder)
+ view.setAlternatingRowColors(True)
# Set view delegates
- version_delegate = VersionDelegate(self.dbcon)
+ version_delegate = VersionDelegate(self.dbcon, view)
column = model.Columns.index("version")
view.setItemDelegateForColumn(column, version_delegate)
- time_delegate = PrettyTimeDelegate()
+ time_delegate = PrettyTimeDelegate(view)
column = model.Columns.index("time")
view.setItemDelegateForColumn(column, time_delegate)
@@ -197,54 +202,39 @@ class SubsetWidget(QtWidgets.QWidget):
layout.addLayout(top_bar_layout)
layout.addWidget(view)
- view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
- view.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
- view.setSortingEnabled(True)
- view.sortByColumn(1, QtCore.Qt.AscendingOrder)
- view.setAlternatingRowColors(True)
-
- self.data = {
- "delegates": {
- "version": version_delegate,
- "time": time_delegate
- },
- "state": {
- "groupable": groupable
- }
- }
-
- self.proxy = proxy
- self.model = model
- self.view = view
- self.filter = subset_filter
- self.family_proxy = family_proxy
-
# settings and connections
- self.proxy.setSourceModel(self.model)
- self.proxy.setDynamicSortFilter(True)
- self.proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
-
- self.view.setModel(self.family_proxy)
- self.view.customContextMenuRequested.connect(self.on_context_menu)
-
for column_name, width in self.default_widths:
idx = model.Columns.index(column_name)
view.setColumnWidth(idx, width)
+ self.model = model
+ self.view = view
+
actual_project = dbcon.Session["AVALON_PROJECT"]
self.on_project_change(actual_project)
+ view.customContextMenuRequested.connect(self.on_context_menu)
+
selection = view.selectionModel()
selection.selectionChanged.connect(self.active_changed)
version_delegate.version_changed.connect(self.version_changed)
- groupable.stateChanged.connect(self.set_grouping)
+ group_checkbox.stateChanged.connect(self.set_grouping)
- self.filter.textChanged.connect(self.proxy.setFilterRegExp)
- self.filter.textChanged.connect(self.view.expandAll)
+ subset_filter.textChanged.connect(proxy.setFilterRegExp)
+ subset_filter.textChanged.connect(view.expandAll)
model.refreshed.connect(self.refreshed)
+ self.proxy = proxy
+ self.family_proxy = family_proxy
+
+ self._subset_filter = subset_filter
+ self._group_checkbox = group_checkbox
+
+ self._version_delegate = version_delegate
+ self._time_delegate = time_delegate
+
self.model.refresh()
def get_subsets_families(self):
@@ -254,7 +244,7 @@ class SubsetWidget(QtWidgets.QWidget):
self.family_proxy.setFamiliesFilter(families)
def is_groupable(self):
- return self.data["state"]["groupable"].checkState()
+ return self._group_checkbox.isChecked()
def set_grouping(self, state):
with tools_lib.preserve_selection(tree_view=self.view,
@@ -755,6 +745,7 @@ class ThumbnailWidget(QtWidgets.QLabel):
"default_thumbnail.png"
)
self.default_pix = QtGui.QPixmap(default_pix_path)
+ self.set_pixmap()
def height(self):
width = self.width()
@@ -786,7 +777,10 @@ class ThumbnailWidget(QtWidgets.QLabel):
def scale_pixmap(self, pixmap):
return pixmap.scaled(
- self.width(), self.height(), QtCore.Qt.KeepAspectRatio
+ self.width(),
+ self.height(),
+ QtCore.Qt.KeepAspectRatio,
+ QtCore.Qt.SmoothTransformation
)
def set_thumbnail(self, entity=None):
@@ -1128,7 +1122,8 @@ class RepresentationWidget(QtWidgets.QWidget):
label = QtWidgets.QLabel("Representations", self)
- tree_view = DeselectableTreeView()
+ tree_view = DeselectableTreeView(parent=self)
+ tree_view.setObjectName("RepresentationView")
tree_view.setModel(proxy_model)
tree_view.setAllColumnsShowFocus(True)
tree_view.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
@@ -1138,12 +1133,6 @@ class RepresentationWidget(QtWidgets.QWidget):
tree_view.sortByColumn(1, QtCore.Qt.AscendingOrder)
tree_view.setAlternatingRowColors(True)
tree_view.setIndentation(20)
- tree_view.setStyleSheet("""
- QTreeView::item{
- padding: 5px 1px;
- border: 0px;
- }
- """)
tree_view.collapseAll()
for column_name, width in self.default_widths:
diff --git a/openpype/tools/settings/local_settings/experimental_widget.py b/openpype/tools/settings/local_settings/experimental_widget.py
index 72f999d886..e863d9afb0 100644
--- a/openpype/tools/settings/local_settings/experimental_widget.py
+++ b/openpype/tools/settings/local_settings/experimental_widget.py
@@ -28,7 +28,7 @@ class LocalExperimentalToolsWidgets(QtWidgets.QWidget):
layout.addRow(empty_label)
- experimental_defs = ExperimentalTools()
+ experimental_defs = ExperimentalTools(filter_hosts=False)
checkboxes_by_identifier = {}
for tool in experimental_defs.tools:
checkbox = QtWidgets.QCheckBox(self)
diff --git a/openpype/tools/utils/delegates.py b/openpype/tools/utils/delegates.py
index 1827bc7e9b..96353c44c6 100644
--- a/openpype/tools/utils/delegates.py
+++ b/openpype/tools/utils/delegates.py
@@ -7,6 +7,7 @@ import Qt
from Qt import QtWidgets, QtGui, QtCore
from avalon.lib import HeroVersionType
+from openpype.style import get_objected_colors
from .models import (
AssetModel,
TreeModel
@@ -24,6 +25,19 @@ log = logging.getLogger(__name__)
class AssetDelegate(QtWidgets.QItemDelegate):
bar_height = 3
+ def __init__(self, *args, **kwargs):
+ super(AssetDelegate, self).__init__(*args, **kwargs)
+ asset_view_colors = get_objected_colors()["loader"]["asset-view"]
+ self._selected_color = (
+ asset_view_colors["selected"].get_qcolor()
+ )
+ self._hover_color = (
+ asset_view_colors["hover"].get_qcolor()
+ )
+ self._selected_hover_color = (
+ asset_view_colors["selected-hover"].get_qcolor()
+ )
+
def sizeHint(self, option, index):
result = super(AssetDelegate, self).sizeHint(option, index)
height = result.height()
@@ -66,17 +80,20 @@ class AssetDelegate(QtWidgets.QItemDelegate):
counter += 1
# Background
- bg_color = QtGui.QColor(60, 60, 60)
if option.state & QtWidgets.QStyle.State_Selected:
if len(subset_colors) == 0:
item_rect.setTop(item_rect.top() + (self.bar_height / 2))
+
if option.state & QtWidgets.QStyle.State_MouseOver:
- bg_color.setRgb(70, 70, 70)
+ bg_color = self._selected_hover_color
+ else:
+ bg_color = self._selected_color
else:
item_rect.setTop(item_rect.top() + (self.bar_height / 2))
if option.state & QtWidgets.QStyle.State_MouseOver:
- bg_color.setAlpha(100)
+ bg_color = self._hover_color
else:
+ bg_color = QtGui.QColor()
bg_color.setAlpha(0)
# When not needed to do a rounded corners (easier and without
diff --git a/openpype/tools/utils/host_tools.py b/openpype/tools/utils/host_tools.py
new file mode 100644
index 0000000000..d5202c8435
--- /dev/null
+++ b/openpype/tools/utils/host_tools.py
@@ -0,0 +1,398 @@
+"""Single access point to all tools usable in hosts.
+
+It is possible to create `HostToolsHelper` in host implementaion or
+use singleton approach with global functions (using helper anyway).
+"""
+
+import avalon.api
+
+
+class HostToolsHelper:
+ """Create and cache tool windows in memory.
+
+ Almost all methods expect parent widget but the parent is used only on
+ first tool creation.
+
+ Class may also contain tools that are available only for one or few hosts.
+ """
+ def __init__(self, parent=None):
+ self._log = None
+ # Global parent for all tools (may and may not be set)
+ self._parent = parent
+
+ # Prepare attributes for all tools
+ self._workfiles_tool = None
+ self._loader_tool = None
+ self._creator_tool = None
+ self._subset_manager_tool = None
+ self._scene_inventory_tool = None
+ self._library_loader_tool = None
+ self._look_assigner_tool = None
+ self._experimental_tools_dialog = None
+
+ @property
+ def log(self):
+ if self._log is None:
+ from openpype.api import Logger
+
+ self._log = Logger.get_logger(self.__class__.__name__)
+ return self._log
+
+ def get_workfiles_tool(self, parent):
+ """Create, cache and return workfiles tool window."""
+ if self._workfiles_tool is None:
+ from openpype.tools.workfiles.app import (
+ Window, validate_host_requirements
+ )
+ # Host validation
+ host = avalon.api.registered_host()
+ validate_host_requirements(host)
+
+ workfiles_window = Window(parent=parent)
+ self._workfiles_tool = workfiles_window
+
+ return self._workfiles_tool
+
+ def show_workfiles(self, parent=None, use_context=None, save=None):
+ """Workfiles tool for changing context and saving workfiles."""
+ from avalon import style
+
+ if use_context is None:
+ use_context = True
+
+ if save is None:
+ save = True
+
+ workfiles_tool = self.get_workfiles_tool(parent)
+ if use_context:
+ context = {
+ "asset": avalon.api.Session["AVALON_ASSET"],
+ "silo": avalon.api.Session["AVALON_SILO"],
+ "task": avalon.api.Session["AVALON_TASK"]
+ }
+ workfiles_tool.set_context(context)
+
+ if save:
+ workfiles_tool.set_save_enabled(save)
+
+ workfiles_tool.refresh()
+ workfiles_tool.show()
+ # Pull window to the front.
+ workfiles_tool.raise_()
+ workfiles_tool.activateWindow()
+ workfiles_tool.setStyleSheet(style.load_stylesheet())
+
+ def get_loader_tool(self, parent):
+ """Create, cache and return loader tool window."""
+ if self._loader_tool is None:
+ from openpype.tools.loader import LoaderWindow
+
+ loader_window = LoaderWindow(parent=parent or self._parent)
+ self._loader_tool = loader_window
+
+ return self._loader_tool
+
+ def show_loader(self, parent=None, use_context=None):
+ """Loader tool for loading representations."""
+ loader_tool = self.get_loader_tool(parent)
+
+ loader_tool.show()
+ loader_tool.raise_()
+ loader_tool.activateWindow()
+
+ if use_context is None:
+ use_context = False
+
+ if use_context:
+ context = {"asset": avalon.api.Session["AVALON_ASSET"]}
+ loader_tool.set_context(context, refresh=True)
+ else:
+ loader_tool.refresh()
+
+ def get_creator_tool(self, parent):
+ """Create, cache and return creator tool window."""
+ if self._creator_tool is None:
+ from avalon.tools.creator.app import Window
+
+ creator_window = Window(parent=parent or self._parent)
+ self._creator_tool = creator_window
+
+ return self._creator_tool
+
+ def show_creator(self, parent=None):
+ """Show tool to create new instantes for publishing."""
+ from avalon import style
+
+ creator_tool = self.get_creator_tool(parent)
+ creator_tool.refresh()
+ creator_tool.show()
+
+ creator_tool.setStyleSheet(style.load_stylesheet())
+
+ # Pull window to the front.
+ creator_tool.raise_()
+ creator_tool.activateWindow()
+
+ def get_subset_manager_tool(self, parent):
+ """Create, cache and return subset manager tool window."""
+ if self._subset_manager_tool is None:
+ from avalon.tools.subsetmanager import Window
+
+ subset_manager_window = Window(parent=parent or self._parent)
+ self._subset_manager_tool = subset_manager_window
+
+ return self._subset_manager_tool
+
+ def show_subset_manager(self, parent=None):
+ """Show tool display/remove existing created instances."""
+ from avalon import style
+
+ subset_manager_tool = self.get_subset_manager_tool(parent)
+ subset_manager_tool.show()
+
+ subset_manager_tool.setStyleSheet(style.load_stylesheet())
+
+ # Pull window to the front.
+ subset_manager_tool.raise_()
+ subset_manager_tool.activateWindow()
+
+ def get_scene_inventory_tool(self, parent):
+ """Create, cache and return scene inventory tool window."""
+ if self._scene_inventory_tool is None:
+ from avalon.tools.sceneinventory.app import Window
+
+ scene_inventory_window = Window(parent=parent or self._parent)
+ self._scene_inventory_tool = scene_inventory_window
+
+ return self._scene_inventory_tool
+
+ def show_scene_inventory(self, parent=None):
+ """Show tool maintain loaded containers."""
+ from avalon import style
+
+ scene_inventory_tool = self.get_scene_inventory_tool(parent)
+ scene_inventory_tool.show()
+ scene_inventory_tool.refresh()
+ scene_inventory_tool.setStyleSheet(style.load_stylesheet())
+
+ # Pull window to the front.
+ scene_inventory_tool.raise_()
+ scene_inventory_tool.activateWindow()
+
+ def get_library_loader_tool(self, parent):
+ """Create, cache and return library loader tool window."""
+ if self._library_loader_tool is None:
+ from openpype.tools.libraryloader import LibraryLoaderWindow
+
+ library_window = LibraryLoaderWindow(
+ parent=parent or self._parent
+ )
+ self._library_loader_tool = library_window
+
+ return self._library_loader_tool
+
+ def show_library_loader(self, parent=None):
+ """Loader tool for loading representations from library project."""
+ library_loader_tool = self.get_library_loader_tool(parent)
+ library_loader_tool.show()
+ library_loader_tool.raise_()
+ library_loader_tool.activateWindow()
+ library_loader_tool.refresh()
+
+ def show_publish(self, parent=None):
+ """Publish UI."""
+ from avalon.tools import publish
+
+ publish.show(parent)
+
+ def get_look_assigner_tool(self, parent):
+ """Create, cache and return look assigner tool window."""
+ if self._look_assigner_tool is None:
+ import mayalookassigner
+
+ mayalookassigner_window = mayalookassigner.App(parent)
+ self._look_assigner_tool = mayalookassigner_window
+ return self._look_assigner_tool
+
+ def show_look_assigner(self, parent=None):
+ """Look manager is Maya specific tool for look management."""
+ from avalon import style
+
+ look_assigner_tool = self.get_look_assigner_tool(parent)
+ look_assigner_tool.show()
+ look_assigner_tool.setStyleSheet(style.load_stylesheet())
+
+ def get_experimental_tools_dialog(self, parent=None):
+ """Dialog of experimental tools.
+
+ For some hosts it is not easy to modify menu of tools. For
+ those cases was addded experimental tools dialog which is Qt based
+ and can dynamically filled by experimental tools so
+ host need only single "Experimental tools" button to see them.
+
+ Dialog can be also empty with a message that there are not available
+ experimental tools.
+ """
+ if self._experimental_tools_dialog is None:
+ from openpype.tools.experimental_tools import (
+ ExperimentalToolsDialog
+ )
+
+ self._experimental_tools_dialog = ExperimentalToolsDialog(parent)
+ return self._experimental_tools_dialog
+
+ def show_experimental_tools_dialog(self, parent=None):
+ """Show dialog with experimental tools."""
+ dialog = self.get_experimental_tools_dialog(parent)
+
+ dialog.show()
+ dialog.raise_()
+ dialog.activateWindow()
+
+ def get_tool_by_name(self, tool_name, parent=None, *args, **kwargs):
+ """Show tool by it's name.
+
+ This is helper for
+ """
+ if tool_name == "workfiles":
+ return self.get_workfiles_tool(parent, *args, **kwargs)
+
+ elif tool_name == "loader":
+ return self.get_loader_tool(parent, *args, **kwargs)
+
+ elif tool_name == "libraryloader":
+ return self.get_library_loader_tool(parent, *args, **kwargs)
+
+ elif tool_name == "creator":
+ return self.get_creator_tool(parent, *args, **kwargs)
+
+ elif tool_name == "subsetmanager":
+ return self.get_subset_manager_tool(parent, *args, **kwargs)
+
+ elif tool_name == "sceneinventory":
+ return self.get_scene_inventory_tool(parent, *args, **kwargs)
+
+ elif tool_name == "lookassigner":
+ return self.get_look_assigner_tool(parent, *args, **kwargs)
+
+ elif tool_name == "publish":
+ self.log.info("Can't return publish tool window.")
+
+ elif tool_name == "experimental_tools":
+ return self.get_experimental_tools_dialog(parent, *args, **kwargs)
+
+ else:
+ self.log.warning(
+ "Can't show unknown tool name: \"{}\"".format(tool_name)
+ )
+
+ def show_tool_by_name(self, tool_name, parent=None, *args, **kwargs):
+ """Show tool by it's name.
+
+ This is helper for
+ """
+ if tool_name == "workfiles":
+ self.show_workfiles(parent, *args, **kwargs)
+
+ elif tool_name == "loader":
+ self.show_loader(parent, *args, **kwargs)
+
+ elif tool_name == "libraryloader":
+ self.show_library_loader(parent, *args, **kwargs)
+
+ elif tool_name == "creator":
+ self.show_creator(parent, *args, **kwargs)
+
+ elif tool_name == "subsetmanager":
+ self.show_subset_manager(parent, *args, **kwargs)
+
+ elif tool_name == "sceneinventory":
+ self.show_scene_inventory(parent, *args, **kwargs)
+
+ elif tool_name == "lookassigner":
+ self.show_look_assigner(parent, *args, **kwargs)
+
+ elif tool_name == "publish":
+ self.show_publish(parent, *args, **kwargs)
+
+ elif tool_name == "experimental_tools":
+ self.show_experimental_tools_dialog(parent, *args, **kwargs)
+
+ else:
+ self.log.warning(
+ "Can't show unknown tool name: \"{}\"".format(tool_name)
+ )
+
+
+class _SingletonPoint:
+ """Singleton access to host tools.
+
+ Some hosts don't have ability to create 'HostToolsHelper' object anc can
+ only register function callbacks. For those cases is created this singleton
+ point where 'HostToolsHelper' is created "in shared memory".
+ """
+ helper = None
+
+ @classmethod
+ def _create_helper(cls):
+ if cls.helper is None:
+ cls.helper = HostToolsHelper()
+
+ @classmethod
+ def show_tool_by_name(cls, tool_name, parent=None, *args, **kwargs):
+ cls._create_helper()
+ cls.helper.show_tool_by_name(tool_name, parent, *args, **kwargs)
+
+ @classmethod
+ def get_tool_by_name(cls, tool_name, parent=None, *args, **kwargs):
+ cls._create_helper()
+ return cls.helper.get_tool_by_name(tool_name, parent, *args, **kwargs)
+
+
+# Function callbacks using singleton acces point
+def get_tool_by_name(tool_name, parent=None, *args, **kwargs):
+ return _SingletonPoint.get_tool_by_name(tool_name, parent, *args, **kwargs)
+
+
+def show_tool_by_name(tool_name, parent=None, *args, **kwargs):
+ _SingletonPoint.show_tool_by_name(tool_name, parent, *args, **kwargs)
+
+
+def show_workfiles(parent=None, use_context=None, save=None):
+ _SingletonPoint.show_tool_by_name(
+ "workfiles", parent, use_context=use_context, save=save
+ )
+
+
+def show_loader(parent=None, use_context=None):
+ _SingletonPoint.show_tool_by_name(
+ "loader", parent, use_context=use_context
+ )
+
+
+def show_library_loader(parent=None):
+ _SingletonPoint.show_tool_by_name("libraryloader", parent)
+
+
+def show_creator(parent=None):
+ _SingletonPoint.show_tool_by_name("creator", parent)
+
+
+def show_subset_manager(parent=None):
+ _SingletonPoint.show_tool_by_name("subsetmanager", parent)
+
+
+def show_scene_inventory(parent=None):
+ _SingletonPoint.show_tool_by_name("sceneinventory", parent)
+
+
+def show_look_assigner(parent=None):
+ _SingletonPoint.show_tool_by_name("lookassigner", parent)
+
+
+def show_publish(parent=None):
+ _SingletonPoint.show_tool_by_name("publish", parent)
+
+
+def show_experimental_tools_dialog(parent=None):
+ _SingletonPoint.show_tool_by_name("experimental_tools", parent)
diff --git a/openpype/tools/utils/views.py b/openpype/tools/utils/views.py
index bed5655647..89e49fe142 100644
--- a/openpype/tools/utils/views.py
+++ b/openpype/tools/utils/views.py
@@ -68,8 +68,8 @@ class AssetsView(TreeViewSpinner, DeselectableTreeView):
This implements a context menu.
"""
- def __init__(self):
- super(AssetsView, self).__init__()
+ def __init__(self, parent=None):
+ super(AssetsView, self).__init__(parent)
self.setIndentation(15)
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.setHeaderHidden(True)
diff --git a/openpype/tools/utils/widgets.py b/openpype/tools/utils/widgets.py
index b9b542c123..15bcbeff90 100644
--- a/openpype/tools/utils/widgets.py
+++ b/openpype/tools/utils/widgets.py
@@ -35,28 +35,19 @@ class AssetWidget(QtWidgets.QWidget):
self.dbcon = dbcon
- self.setContentsMargins(0, 0, 0, 0)
-
- layout = QtWidgets.QVBoxLayout(self)
- layout.setContentsMargins(0, 0, 0, 0)
- layout.setSpacing(4)
-
# Tree View
model = AssetModel(dbcon=self.dbcon, parent=self)
proxy = RecursiveSortFilterProxyModel()
proxy.setSourceModel(model)
proxy.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
- view = AssetsView()
+ view = AssetsView(self)
view.setModel(proxy)
if multiselection:
asset_delegate = AssetDelegate()
view.setSelectionMode(view.ExtendedSelection)
view.setItemDelegate(asset_delegate)
- # Header
- header = QtWidgets.QHBoxLayout()
-
icon = qtawesome.icon("fa.arrow-down", color=style.colors.light)
set_current_asset_btn = QtWidgets.QPushButton(icon, "")
set_current_asset_btn.setToolTip("Go to Asset from current Session")
@@ -64,22 +55,28 @@ class AssetWidget(QtWidgets.QWidget):
set_current_asset_btn.setVisible(False)
icon = qtawesome.icon("fa.refresh", color=style.colors.light)
- refresh = QtWidgets.QPushButton(icon, "")
+ refresh = QtWidgets.QPushButton(icon, "", parent=self)
refresh.setToolTip("Refresh items")
- filter = QtWidgets.QLineEdit()
- filter.textChanged.connect(proxy.setFilterFixedString)
- filter.setPlaceholderText("Filter assets..")
+ filter_input = QtWidgets.QLineEdit(self)
+ filter_input.setPlaceholderText("Filter assets..")
- header.addWidget(filter)
- header.addWidget(set_current_asset_btn)
- header.addWidget(refresh)
+ # Header
+ header_layout = QtWidgets.QHBoxLayout()
+ header_layout.addWidget(filter_input)
+ header_layout.addWidget(set_current_asset_btn)
+ header_layout.addWidget(refresh)
# Layout
- layout.addLayout(header)
+ layout = QtWidgets.QVBoxLayout(self)
+ layout.setContentsMargins(0, 0, 0, 0)
+ layout.setSpacing(4)
+ layout.addLayout(header_layout)
layout.addWidget(view)
# Signals/Slots
+ filter_input.textChanged.connect(proxy.setFilterFixedString)
+
selection = view.selectionModel()
selection.selectionChanged.connect(self.selection_changed)
selection.currentChanged.connect(self.current_changed)
@@ -313,7 +310,6 @@ class OptionalMenu(QtWidgets.QMenu):
actions that were instances of `QtWidgets.QWidgetAction`.
"""
-
def mouseReleaseEvent(self, event):
"""Emit option clicked signal if mouse released on it"""
active = self.actionAt(event.pos())
@@ -352,6 +348,7 @@ class OptionalAction(QtWidgets.QWidgetAction):
self.use_option = use_option
self.option_tip = ""
self.optioned = False
+ self.widget = None
def createWidget(self, parent):
widget = OptionalActionWidget(self.label, parent)
@@ -377,20 +374,10 @@ class OptionalAction(QtWidgets.QWidgetAction):
self.optioned = True
def set_highlight(self, state, global_pos=None):
- body = self.widget.body
- option = self.widget.option
-
- role = QtGui.QPalette.Highlight if state else QtGui.QPalette.Window
- body.setBackgroundRole(role)
- body.setAutoFillBackground(state)
-
- if not self.use_option:
- return
-
- state = option.is_hovered(global_pos)
- role = QtGui.QPalette.Highlight if state else QtGui.QPalette.Window
- option.setBackgroundRole(role)
- option.setAutoFillBackground(state)
+ option_state = False
+ if self.use_option:
+ option_state = self.widget.option.is_hovered(global_pos)
+ self.widget.set_hover_properties(state, option_state)
class OptionalActionWidget(QtWidgets.QWidget):
@@ -399,30 +386,33 @@ class OptionalActionWidget(QtWidgets.QWidget):
def __init__(self, label, parent=None):
super(OptionalActionWidget, self).__init__(parent)
- body = QtWidgets.QWidget()
- body.setStyleSheet("background: transparent;")
+ body_widget = QtWidgets.QWidget(self)
+ body_widget.setObjectName("OptionalActionBody")
- icon = QtWidgets.QLabel()
- label = QtWidgets.QLabel(label)
- option = OptionBox(body)
+ icon = QtWidgets.QLabel(body_widget)
+ label = QtWidgets.QLabel(label, body_widget)
+ # (NOTE) For removing ugly QLable shadow FX when highlighted in Nuke.
+ # See https://stackoverflow.com/q/52838690/4145300
+ label.setStyle(QtWidgets.QStyleFactory.create("Plastique"))
+ option = OptionBox(body_widget)
+ option.setObjectName("OptionalActionOption")
icon.setFixedSize(24, 16)
option.setFixedSize(30, 30)
- layout = QtWidgets.QHBoxLayout(body)
- layout.setContentsMargins(0, 0, 0, 0)
- layout.setSpacing(2)
- layout.addWidget(icon)
- layout.addWidget(label)
- layout.addSpacing(6)
+ body_layout = QtWidgets.QHBoxLayout(body_widget)
+ body_layout.setContentsMargins(4, 0, 4, 0)
+ body_layout.setSpacing(2)
+ body_layout.addWidget(icon)
+ body_layout.addWidget(label)
layout = QtWidgets.QHBoxLayout(self)
- layout.setContentsMargins(6, 1, 2, 1)
+ layout.setContentsMargins(2, 1, 2, 1)
layout.setSpacing(0)
- layout.addWidget(body)
+ layout.addWidget(body_widget)
layout.addWidget(option)
- body.setMouseTracking(True)
+ body_widget.setMouseTracking(True)
label.setMouseTracking(True)
option.setMouseTracking(True)
self.setMouseTracking(True)
@@ -431,11 +421,24 @@ class OptionalActionWidget(QtWidgets.QWidget):
self.icon = icon
self.label = label
self.option = option
- self.body = body
+ self.body = body_widget
- # (NOTE) For removing ugly QLable shadow FX when highlighted in Nuke.
- # See https://stackoverflow.com/q/52838690/4145300
- label.setStyle(QtWidgets.QStyleFactory.create("Plastique"))
+ def set_hover_properties(self, hovered, option_hovered):
+ body_state = ""
+ option_state = ""
+ if hovered:
+ body_state = "hover"
+
+ if option_hovered:
+ option_state = "hover"
+
+ if self.body.property("state") != body_state:
+ self.body.setProperty("state", body_state)
+ self.body.style().polish(self.body)
+
+ if self.option.property("state") != option_state:
+ self.option.setProperty("state", option_state)
+ self.option.style().polish(self.option)
def setIcon(self, icon):
pixmap = icon.pixmap(16, 16)
@@ -456,8 +459,6 @@ class OptionBox(QtWidgets.QLabel):
pixmap = icon.pixmap(18, 18)
self.setPixmap(pixmap)
- self.setStyleSheet("background: transparent;")
-
def is_hovered(self, global_pos):
if global_pos is None:
return False
@@ -476,20 +477,20 @@ class OptionDialog(QtWidgets.QDialog):
def create(self, options):
parser = qargparse.QArgumentParser(arguments=options)
- decision = QtWidgets.QWidget()
- accept = QtWidgets.QPushButton("Accept")
- cancel = QtWidgets.QPushButton("Cancel")
+ decision_widget = QtWidgets.QWidget(self)
+ accept_btn = QtWidgets.QPushButton("Accept", decision_widget)
+ cancel_btn = QtWidgets.QPushButton("Cancel", decision_widget)
- layout = QtWidgets.QHBoxLayout(decision)
- layout.addWidget(accept)
- layout.addWidget(cancel)
+ decision_layout = QtWidgets.QHBoxLayout(decision_widget)
+ decision_layout.addWidget(accept_btn)
+ decision_layout.addWidget(cancel_btn)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(parser)
- layout.addWidget(decision)
+ layout.addWidget(decision_widget)
- accept.clicked.connect(self.accept)
- cancel.clicked.connect(self.reject)
+ accept_btn.clicked.connect(self.accept)
+ cancel_btn.clicked.connect(self.reject)
parser.changed.connect(self.on_changed)
def on_changed(self, argument):
diff --git a/openpype/tools/workfiles/app.py b/openpype/tools/workfiles/app.py
index 6fff0d0278..1679a18241 100644
--- a/openpype/tools/workfiles/app.py
+++ b/openpype/tools/workfiles/app.py
@@ -944,7 +944,10 @@ class Window(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent=parent)
self.setWindowTitle(self.title)
- self.setWindowFlags(QtCore.Qt.Window | QtCore.Qt.WindowCloseButtonHint)
+ window_flags = QtCore.Qt.Window | QtCore.Qt.WindowCloseButtonHint
+ if not parent:
+ window_flags |= QtCore.Qt.WindowStaysOnTopHint
+ self.setWindowFlags(window_flags)
# Create pages widget and set it as central widget
pages_widget = QtWidgets.QStackedWidget(self)
@@ -1015,6 +1018,9 @@ class Window(QtWidgets.QMainWindow):
"""
+ def set_save_enabled(self, enabled):
+ self.files_widget.btn_save.setEnabled(enabled)
+
def on_task_changed(self):
# Since we query the disk give it slightly more delay
tools_lib.schedule(self._on_task_changed, 100, channel="mongo")
@@ -1187,7 +1193,7 @@ def show(root=None, debug=False, parent=None, use_context=True, save=True):
}
window.set_context(context)
- window.files_widget.btn_save.setEnabled(save)
+ window.set_save_enabled(save)
window.show()
window.setStyleSheet(style.load_stylesheet())
diff --git a/poetry.lock b/poetry.lock
index e5f5919a01..36105f4213 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -782,7 +782,7 @@ six = "*"
[[package]]
name = "pillow"
-version = "8.2.0"
+version = "8.3.2"
description = "Python Imaging Library (Fork)"
category = "main"
optional = false
@@ -1538,7 +1538,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt
[metadata]
lock-version = "1.1"
python-versions = "3.7.*"
-content-hash = "ff2bfa35a7304378917a0c25d7d7af9f81a130288d95789bdf7429f071e80b69"
+content-hash = "fb6db80d126fe7ef2d1d06d0381b6d11445d6d3e54b33585f6b0a0b6b0b9d372"
[metadata.files]
acre = []
@@ -2058,40 +2058,59 @@ pathlib2 = [
{file = "pathlib2-2.3.5.tar.gz", hash = "sha256:6cd9a47b597b37cc57de1c05e56fb1a1c9cc9fab04fe78c29acd090418529868"},
]
pillow = [
- {file = "Pillow-8.2.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:dc38f57d8f20f06dd7c3161c59ca2c86893632623f33a42d592f097b00f720a9"},
- {file = "Pillow-8.2.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a013cbe25d20c2e0c4e85a9daf438f85121a4d0344ddc76e33fd7e3965d9af4b"},
- {file = "Pillow-8.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8bb1e155a74e1bfbacd84555ea62fa21c58e0b4e7e6b20e4447b8d07990ac78b"},
- {file = "Pillow-8.2.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c5236606e8570542ed424849f7852a0ff0bce2c4c8d0ba05cc202a5a9c97dee9"},
- {file = "Pillow-8.2.0-cp36-cp36m-win32.whl", hash = "sha256:12e5e7471f9b637762453da74e390e56cc43e486a88289995c1f4c1dc0bfe727"},
- {file = "Pillow-8.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5afe6b237a0b81bd54b53f835a153770802f164c5570bab5e005aad693dab87f"},
- {file = "Pillow-8.2.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:cb7a09e173903541fa888ba010c345893cd9fc1b5891aaf060f6ca77b6a3722d"},
- {file = "Pillow-8.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0d19d70ee7c2ba97631bae1e7d4725cdb2ecf238178096e8c82ee481e189168a"},
- {file = "Pillow-8.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:083781abd261bdabf090ad07bb69f8f5599943ddb539d64497ed021b2a67e5a9"},
- {file = "Pillow-8.2.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:c6b39294464b03457f9064e98c124e09008b35a62e3189d3513e5148611c9388"},
- {file = "Pillow-8.2.0-cp37-cp37m-win32.whl", hash = "sha256:01425106e4e8cee195a411f729cff2a7d61813b0b11737c12bd5991f5f14bcd5"},
- {file = "Pillow-8.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3b570f84a6161cf8865c4e08adf629441f56e32f180f7aa4ccbd2e0a5a02cba2"},
- {file = "Pillow-8.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:031a6c88c77d08aab84fecc05c3cde8414cd6f8406f4d2b16fed1e97634cc8a4"},
- {file = "Pillow-8.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:66cc56579fd91f517290ab02c51e3a80f581aba45fd924fcdee01fa06e635812"},
- {file = "Pillow-8.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6c32cc3145928c4305d142ebec682419a6c0a8ce9e33db900027ddca1ec39178"},
- {file = "Pillow-8.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:624b977355cde8b065f6d51b98497d6cd5fbdd4f36405f7a8790e3376125e2bb"},
- {file = "Pillow-8.2.0-cp38-cp38-win32.whl", hash = "sha256:5cbf3e3b1014dddc45496e8cf38b9f099c95a326275885199f427825c6522232"},
- {file = "Pillow-8.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:463822e2f0d81459e113372a168f2ff59723e78528f91f0bd25680ac185cf797"},
- {file = "Pillow-8.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:95d5ef984eff897850f3a83883363da64aae1000e79cb3c321915468e8c6add5"},
- {file = "Pillow-8.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b91c36492a4bbb1ee855b7d16fe51379e5f96b85692dc8210831fbb24c43e484"},
- {file = "Pillow-8.2.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d68cb92c408261f806b15923834203f024110a2e2872ecb0bd2a110f89d3c602"},
- {file = "Pillow-8.2.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f217c3954ce5fd88303fc0c317af55d5e0204106d86dea17eb8205700d47dec2"},
- {file = "Pillow-8.2.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5b70110acb39f3aff6b74cf09bb4169b167e2660dabc304c1e25b6555fa781ef"},
- {file = "Pillow-8.2.0-cp39-cp39-win32.whl", hash = "sha256:a7d5e9fad90eff8f6f6106d3b98b553a88b6f976e51fce287192a5d2d5363713"},
- {file = "Pillow-8.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:238c197fc275b475e87c1453b05b467d2d02c2915fdfdd4af126145ff2e4610c"},
- {file = "Pillow-8.2.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:0e04d61f0064b545b989126197930807c86bcbd4534d39168f4aa5fda39bb8f9"},
- {file = "Pillow-8.2.0-pp36-pypy36_pp73-manylinux2010_i686.whl", hash = "sha256:63728564c1410d99e6d1ae8e3b810fe012bc440952168af0a2877e8ff5ab96b9"},
- {file = "Pillow-8.2.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:c03c07ed32c5324939b19e36ae5f75c660c81461e312a41aea30acdd46f93a7c"},
- {file = "Pillow-8.2.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:4d98abdd6b1e3bf1a1cbb14c3895226816e666749ac040c4e2554231068c639b"},
- {file = "Pillow-8.2.0-pp37-pypy37_pp73-manylinux2010_i686.whl", hash = "sha256:aac00e4bc94d1b7813fe882c28990c1bc2f9d0e1aa765a5f2b516e8a6a16a9e4"},
- {file = "Pillow-8.2.0-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:22fd0f42ad15dfdde6c581347eaa4adb9a6fc4b865f90b23378aa7914895e120"},
- {file = "Pillow-8.2.0-pp37-pypy37_pp73-win32.whl", hash = "sha256:e98eca29a05913e82177b3ba3d198b1728e164869c613d76d0de4bde6768a50e"},
- {file = "Pillow-8.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:8b56553c0345ad6dcb2e9b433ae47d67f95fc23fe28a0bde15a120f25257e291"},
- {file = "Pillow-8.2.0.tar.gz", hash = "sha256:a787ab10d7bb5494e5f76536ac460741788f1fbce851068d73a87ca7c35fc3e1"},
+ {file = "Pillow-8.3.2-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:c691b26283c3a31594683217d746f1dad59a7ae1d4cfc24626d7a064a11197d4"},
+ {file = "Pillow-8.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f514c2717012859ccb349c97862568fdc0479aad85b0270d6b5a6509dbc142e2"},
+ {file = "Pillow-8.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be25cb93442c6d2f8702c599b51184bd3ccd83adebd08886b682173e09ef0c3f"},
+ {file = "Pillow-8.3.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d675a876b295afa114ca8bf42d7f86b5fb1298e1b6bb9a24405a3f6c8338811c"},
+ {file = "Pillow-8.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59697568a0455764a094585b2551fd76bfd6b959c9f92d4bdec9d0e14616303a"},
+ {file = "Pillow-8.3.2-cp310-cp310-win32.whl", hash = "sha256:2d5e9dc0bf1b5d9048a94c48d0813b6c96fccfa4ccf276d9c36308840f40c228"},
+ {file = "Pillow-8.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:11c27e74bab423eb3c9232d97553111cc0be81b74b47165f07ebfdd29d825875"},
+ {file = "Pillow-8.3.2-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:11eb7f98165d56042545c9e6db3ce394ed8b45089a67124298f0473b29cb60b2"},
+ {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f23b2d3079522fdf3c09de6517f625f7a964f916c956527bed805ac043799b8"},
+ {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19ec4cfe4b961edc249b0e04b5618666c23a83bc35842dea2bfd5dfa0157f81b"},
+ {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5a31c07cea5edbaeb4bdba6f2b87db7d3dc0f446f379d907e51cc70ea375629"},
+ {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15ccb81a6ffc57ea0137f9f3ac2737ffa1d11f786244d719639df17476d399a7"},
+ {file = "Pillow-8.3.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8f284dc1695caf71a74f24993b7c7473d77bc760be45f776a2c2f4e04c170550"},
+ {file = "Pillow-8.3.2-cp36-cp36m-win32.whl", hash = "sha256:4abc247b31a98f29e5224f2d31ef15f86a71f79c7f4d2ac345a5d551d6393073"},
+ {file = "Pillow-8.3.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a048dad5ed6ad1fad338c02c609b862dfaa921fcd065d747194a6805f91f2196"},
+ {file = "Pillow-8.3.2-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:06d1adaa284696785375fa80a6a8eb309be722cf4ef8949518beb34487a3df71"},
+ {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd24054aaf21e70a51e2a2a5ed1183560d3a69e6f9594a4bfe360a46f94eba83"},
+ {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a330bf7014ee034046db43ccbb05c766aa9e70b8d6c5260bfc38d73103b0ba"},
+ {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13654b521fb98abdecec105ea3fb5ba863d1548c9b58831dd5105bb3873569f1"},
+ {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a1bd983c565f92779be456ece2479840ec39d386007cd4ae83382646293d681b"},
+ {file = "Pillow-8.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4326ea1e2722f3dc00ed77c36d3b5354b8fb7399fb59230249ea6d59cbed90da"},
+ {file = "Pillow-8.3.2-cp37-cp37m-win32.whl", hash = "sha256:085a90a99404b859a4b6c3daa42afde17cb3ad3115e44a75f0d7b4a32f06a6c9"},
+ {file = "Pillow-8.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:18a07a683805d32826c09acfce44a90bf474e6a66ce482b1c7fcd3757d588df3"},
+ {file = "Pillow-8.3.2-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4e59e99fd680e2b8b11bbd463f3c9450ab799305d5f2bafb74fefba6ac058616"},
+ {file = "Pillow-8.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4d89a2e9219a526401015153c0e9dd48319ea6ab9fe3b066a20aa9aee23d9fd3"},
+ {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56fd98c8294f57636084f4b076b75f86c57b2a63a8410c0cd172bc93695ee979"},
+ {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b11c9d310a3522b0fd3c35667914271f570576a0e387701f370eb39d45f08a4"},
+ {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0412516dcc9de9b0a1e0ae25a280015809de8270f134cc2c1e32c4eeb397cf30"},
+ {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bcb04ff12e79b28be6c9988f275e7ab69f01cc2ba319fb3114f87817bb7c74b6"},
+ {file = "Pillow-8.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0b9911ec70731711c3b6ebcde26caea620cbdd9dcb73c67b0730c8817f24711b"},
+ {file = "Pillow-8.3.2-cp38-cp38-win32.whl", hash = "sha256:ce2e5e04bb86da6187f96d7bab3f93a7877830981b37f0287dd6479e27a10341"},
+ {file = "Pillow-8.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:35d27687f027ad25a8d0ef45dd5208ef044c588003cdcedf05afb00dbc5c2deb"},
+ {file = "Pillow-8.3.2-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:04835e68ef12904bc3e1fd002b33eea0779320d4346082bd5b24bec12ad9c3e9"},
+ {file = "Pillow-8.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:10e00f7336780ca7d3653cf3ac26f068fa11b5a96894ea29a64d3dc4b810d630"},
+ {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cde7a4d3687f21cffdf5bb171172070bb95e02af448c4c8b2f223d783214056"},
+ {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c3ff00110835bdda2b1e2b07f4a2548a39744bb7de5946dc8e95517c4fb2ca6"},
+ {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35d409030bf3bd05fa66fb5fdedc39c521b397f61ad04309c90444e893d05f7d"},
+ {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bff50ba9891be0a004ef48828e012babaaf7da204d81ab9be37480b9020a82b"},
+ {file = "Pillow-8.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7dbfbc0020aa1d9bc1b0b8bcf255a7d73f4ad0336f8fd2533fcc54a4ccfb9441"},
+ {file = "Pillow-8.3.2-cp39-cp39-win32.whl", hash = "sha256:963ebdc5365d748185fdb06daf2ac758116deecb2277ec5ae98139f93844bc09"},
+ {file = "Pillow-8.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:cc9d0dec711c914ed500f1d0d3822868760954dce98dfb0b7382a854aee55d19"},
+ {file = "Pillow-8.3.2-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2c661542c6f71dfd9dc82d9d29a8386287e82813b0375b3a02983feac69ef864"},
+ {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:548794f99ff52a73a156771a0402f5e1c35285bd981046a502d7e4793e8facaa"},
+ {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8b68f565a4175e12e68ca900af8910e8fe48aaa48fd3ca853494f384e11c8bcd"},
+ {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:838eb85de6d9307c19c655c726f8d13b8b646f144ca6b3771fa62b711ebf7624"},
+ {file = "Pillow-8.3.2-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:feb5db446e96bfecfec078b943cc07744cc759893cef045aa8b8b6d6aaa8274e"},
+ {file = "Pillow-8.3.2-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:fc0db32f7223b094964e71729c0361f93db43664dd1ec86d3df217853cedda87"},
+ {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fd4fd83aa912d7b89b4b4a1580d30e2a4242f3936882a3f433586e5ab97ed0d5"},
+ {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d0c8ebbfd439c37624db98f3877d9ed12c137cadd99dde2d2eae0dab0bbfc355"},
+ {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6cb3dd7f23b044b0737317f892d399f9e2f0b3a02b22b2c692851fb8120d82c6"},
+ {file = "Pillow-8.3.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a66566f8a22561fc1a88dc87606c69b84fa9ce724f99522cf922c801ec68f5c1"},
+ {file = "Pillow-8.3.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ce651ca46d0202c302a535d3047c55a0131a720cf554a578fc1b8a2aff0e7d96"},
+ {file = "Pillow-8.3.2.tar.gz", hash = "sha256:dde3f3ed8d00c72631bc19cbfff8ad3b6215062a5eed402381ad365f82f0c18c"},
]
pluggy = [
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
@@ -2294,6 +2313,7 @@ pynput = [
pyobjc-core = [
{file = "pyobjc-core-7.3.tar.gz", hash = "sha256:5081aedf8bb40aac1a8ad95adac9e44e148a882686ded614adf46bb67fd67574"},
{file = "pyobjc_core-7.3-1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a1f1e6b457127cbf2b5bd2b94520a7c89fb590b739911eadb2b0499a3a5b0e6f"},
+ {file = "pyobjc_core-7.3-1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:ed708cc47bae8b711f81f252af09898a5f986c7a38cec5ad5623d571d328bff8"},
{file = "pyobjc_core-7.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4e93ad769a20b908778fe950f62a843a6d8f0fa71996e5f3cc9fab5ae7d17771"},
{file = "pyobjc_core-7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f63fd37bbf3785af4ddb2f86cad5ca81c62cfc7d1c0099637ca18343c3656c1"},
{file = "pyobjc_core-7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9b1311f72f2e170742a7ee3a8149f52c35158dc024a21e88d6f1e52ba5d718b"},
@@ -2303,6 +2323,7 @@ pyobjc-core = [
pyobjc-framework-cocoa = [
{file = "pyobjc-framework-Cocoa-7.3.tar.gz", hash = "sha256:b18d05e7a795a3455ad191c3e43d6bfa673c2a4fd480bb1ccf57191051b80b7e"},
{file = "pyobjc_framework_Cocoa-7.3-1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1e31376806e5de883a1d7c7c87d9ff2a8b09fc05d267e0dfce6e42409fb70c67"},
+ {file = "pyobjc_framework_Cocoa-7.3-1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d999387927284346035cb63ebb51f86331abc41f9376f9a6970e7f18207db392"},
{file = "pyobjc_framework_Cocoa-7.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9edffdfa6dd1f71f21b531c3e61fdd3e4d5d3bf6c5a528c98e88828cd60bac11"},
{file = "pyobjc_framework_Cocoa-7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:35a6340437a4e0109a302150b7d1f6baf57004ccf74834f9e6062fcafe2fd8d7"},
{file = "pyobjc_framework_Cocoa-7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7c3886f2608ab3ed02482f8b2ebf9f782b324c559e84b52cfd92dba8a1109872"},
@@ -2312,6 +2333,7 @@ pyobjc-framework-cocoa = [
pyobjc-framework-quartz = [
{file = "pyobjc-framework-Quartz-7.3.tar.gz", hash = "sha256:98812844c34262def980bdf60923a875cd43428a8375b6fd53bd2cd800eccf0b"},
{file = "pyobjc_framework_Quartz-7.3-1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1139bc6874c0f8b58f0b8602015e0994198bc506a6bcec1071208de32b55ed26"},
+ {file = "pyobjc_framework_Quartz-7.3-1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d94a3ed7051266c52392ec07d3b5adbf28d4be83341a24df0d88639344dcd84f"},
{file = "pyobjc_framework_Quartz-7.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1ef18f5a16511ded65980bf4f5983ea5d35c88224dbad1b3112abd29c60413ea"},
{file = "pyobjc_framework_Quartz-7.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3b41eec8d4b10c7c7e011e2f9051367f5499ef315ba52dfbae573c3a2e05469c"},
{file = "pyobjc_framework_Quartz-7.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c65456ed045dfe1711d0298734e5a3ad670f8c770f7eb3b19979256c388bdd2"},
diff --git a/pyproject.toml b/pyproject.toml
index 085538d306..dade0a2f57 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -45,7 +45,7 @@ jsonschema = "^3.2.0"
keyring = "^22.0.1"
log4mongo = "^1.7"
pathlib2= "^2.3.5" # deadline submit publish job only (single place, maybe not needed?)
-Pillow = "^8.1" # only used for slates prototype
+Pillow = "^8.3" # only used for slates prototype
pyblish-base = "^1.8.8"
pynput = "^1.7.2" # idle manager in tray
pymongo = "^3.11.2"
diff --git a/tools/ci_tools.py b/tools/ci_tools.py
index 337b19a346..e5ca0c2c28 100644
--- a/tools/ci_tools.py
+++ b/tools/ci_tools.py
@@ -27,7 +27,7 @@ def get_release_type_github(Log, github_token):
return "minor"
if any(label in labels for label in patch_labels):
- return "path"
+ return "patch"
return None
diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js
index 3ce1cde060..ddbcfd9ce7 100644
--- a/website/docusaurus.config.js
+++ b/website/docusaurus.config.js
@@ -116,8 +116,8 @@ module.exports = {
// Optional: Algolia search parameters
searchParameters: {},
},
- googleAnalytics: {
- trackingID: 'G-HHJZ9VF0FG',
+ gtag: {
+ trackingID: 'G-DTKXMFENFY',
// Optional fields.
anonymizeIP: false, // Should IPs be anonymized?
},
diff --git a/website/yarn.lock b/website/yarn.lock
index 066d156d97..ae40005384 100644
--- a/website/yarn.lock
+++ b/website/yarn.lock
@@ -2175,11 +2175,11 @@ autoprefixer@^10.0.2, autoprefixer@^10.2.5:
postcss-value-parser "^4.1.0"
axios@^0.21.1:
- version "0.21.1"
- resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
- integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
+ version "0.21.4"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
+ integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
dependencies:
- follow-redirects "^1.10.0"
+ follow-redirects "^1.14.0"
babel-loader@^8.2.2:
version "8.2.2"
@@ -3982,10 +3982,10 @@ flux@^4.0.1:
fbemitter "^3.0.0"
fbjs "^3.0.0"
-follow-redirects@^1.0.0, follow-redirects@^1.10.0:
- version "1.13.3"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267"
- integrity sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==
+follow-redirects@^1.0.0, follow-redirects@^1.14.0:
+ version "1.14.4"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
+ integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
for-in@^1.0.2:
version "1.0.2"