From d72e38addfb04d176d992a2f9f28ac06b3414129 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 15 Feb 2021 11:38:35 +0100 Subject: [PATCH 01/83] copied project schemas to entities dir --- .../schemas/projects_schema/schema_main.json | 76 ++ .../projects_schema/schema_plugins.json | 54 ++ .../schema_project_celaction.json | 62 ++ .../schema_project_ftrack.json | 663 ++++++++++++++++++ .../schema_project_global.json | 33 + .../schema_project_harmony.json | 36 + .../projects_schema/schema_project_hiero.json | 172 +++++ .../projects_schema/schema_project_maya.json | 29 + .../projects_schema/schema_project_nuke.json | 193 +++++ .../schema_project_resolve.json | 124 ++++ .../schema_project_standalonepublisher.json | 93 +++ .../schema_project_syncserver.json | 76 ++ .../schema_project_unreal.json | 27 + .../schemas/schema_anatomy_attributes.json | 79 +++ .../schemas/schema_anatomy_imageio.json | 353 ++++++++++ .../schemas/schema_anatomy_templates.json | 135 ++++ .../schemas/schema_global_publish.json | 407 +++++++++++ .../schemas/schema_global_tools.json | 77 ++ .../schemas/schema_maya_capture.json | 595 ++++++++++++++++ .../schemas/schema_maya_load.json | 156 +++++ .../schemas/schema_maya_publish.json | 214 ++++++ .../schemas/schema_publish_gui_filter.json | 10 + .../schemas/schema_workfile_build.json | 97 +++ .../schemas/template_color.json | 30 + 24 files changed, 3791 insertions(+) create mode 100644 pype/settings/entities/schemas/projects_schema/schema_main.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_plugins.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_celaction.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_global.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_harmony.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_hiero.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_maya.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_nuke.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_resolve.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_standalonepublisher.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_syncserver.json create mode 100644 pype/settings/entities/schemas/projects_schema/schema_project_unreal.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/schema_publish_gui_filter.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json create mode 100644 pype/settings/entities/schemas/projects_schema/schemas/template_color.json diff --git a/pype/settings/entities/schemas/projects_schema/schema_main.json b/pype/settings/entities/schemas/projects_schema/schema_main.json new file mode 100644 index 0000000000..73266a9e79 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_main.json @@ -0,0 +1,76 @@ +{ + "key": "project", + "type": "dict", + "children": [ + { + "type": "anatomy", + "key": "project_anatomy", + "children": [ + { + "type": "anatomy_roots", + "key": "roots", + "label": "Roots", + "is_file": true + }, + { + "type": "schema", + "name": "schema_anatomy_templates" + }, + { + "type": "schema", + "name": "schema_anatomy_attributes" + }, + { + "type": "schema", + "name": "schema_anatomy_imageio" + } + ] + }, + { + "type": "dict", + "key": "project_settings", + "children": [ + { + "type": "schema", + "name": "schema_project_global" + }, + { + "type": "schema", + "name": "schema_project_ftrack" + }, + { + "type": "schema", + "name": "schema_project_maya" + }, + { + "type": "schema", + "name": "schema_project_nuke" + }, + { + "type": "schema", + "name": "schema_project_hiero" + }, + { + "type": "schema", + "name": "schema_project_harmony" + }, + { + "type": "schema", + "name": "schema_project_celaction" + }, + { + "type": "schema", + "name": "schema_project_resolve" + }, + { + "type": "schema", + "name": "schema_project_standalonepublisher" + }, + { + "type": "schema", + "name": "schema_project_unreal" + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_plugins.json b/pype/settings/entities/schemas/projects_schema/schema_plugins.json new file mode 100644 index 0000000000..ce90ceb881 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_plugins.json @@ -0,0 +1,54 @@ +{ + "type": "dict", + "collapsable": true, + "key": "plugins", + "label": "Plugins", + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "standalonepublisher", + "label": "Standalone Publisher", + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "publish", + "label": "Publish plugins", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "ExtractThumbnailSP", + "label": "ExtractThumbnailSP", + "is_group": true, + "children": [ + { + "type": "dict", + "collapsable": false, + "key": "ffmpeg_args", + "label": "ffmpeg_args", + "children": [ + { + "type": "list", + "object_type": "text", + "key": "input", + "label": "input" + }, + { + "type": "list", + "object_type": "text", + "key": "output", + "label": "output" + } + ] + } + ] + } + ] + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_celaction.json b/pype/settings/entities/schemas/projects_schema/schema_project_celaction.json new file mode 100644 index 0000000000..86d6141c4a --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_celaction.json @@ -0,0 +1,62 @@ +{ + "type": "dict", + "collapsable": true, + "key": "celaction", + "label": "CelAction", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "publish", + "label": "Publish plugins", + "children": [ + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "ExtractCelactionDeadline", + "label": "ExtractCelactionDeadline", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "text", + "key": "deadline_department", + "label": "Deadline apartment" + }, + { + "type": "number", + "key": "deadline_priority", + "label": "Deadline priority" + }, + { + "type": "text", + "key": "deadline_pool", + "label": "Deadline pool" + }, + { + "type": "text", + "key": "deadline_pool_secondary", + "label": "Deadline pool (secondary)" + }, + { + "type": "text", + "key": "deadline_group", + "label": "Deadline Group" + }, + { + "type": "number", + "key": "deadline_chunk_size", + "label": "Deadline Chunk size" + } + ] + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json new file mode 100644 index 0000000000..508b8e870d --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -0,0 +1,663 @@ +{ + "type": "dict", + "key": "ftrack", + "label": "Ftrack", + "collapsable": true, + "checkbox_key": "enabled", + "is_file": true, + "children": [ + { + "type": "splitter" + }, + { + "type": "label", + "label": "Additional Ftrack paths" + }, + { + "type": "list", + "key": "ftrack_actions_path", + "label": "Action paths", + "object_type": "text" + }, + { + "type": "list", + "key": "ftrack_events_path", + "label": "Event paths", + "object_type": "text" + }, + { + "type": "splitter" + }, + { + "type": "dict", + "key": "events", + "label": "Server Actions/Events", + "children": [ + { + "type": "dict", + "key": "sync_to_avalon", + "label": "Sync to avalon", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Allow name and hierarchy change only if following statuses are on all children tasks" + }, + { + "type": "list", + "key": "statuses_name_change", + "label": "Statuses", + "object_type": { + "type": "text", + "multiline": false + } + } + ] + }, + { + "type": "dict", + "key": "sync_hier_entity_attributes", + "label": "Sync Hierarchical and Entity Attributes", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "interest_entity_types", + "label": "Entity types of interest", + "object_type": { + "type": "text", + "multiline": false + } + }, + { + "type": "list", + "key": "interest_attributes", + "label": "Attributes to sync", + "object_type": { + "type": "text", + "multiline": false + } + }, + { + "type": "separator" + }, + { + "type": "boolean", + "key": "action_enabled", + "label": "Enable Action" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles for action", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "clone_review_session", + "label": "Clone Review Session", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles for action", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "thumbnail_updates", + "label": "Update Hierarchy thumbnails", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Push thumbnail from version, up through multiple hierarchy levels." + }, + { + "type": "number", + "key": "levels", + "label": "Levels" + } + ] + }, + { + "type": "dict", + "key": "user_assignment", + "label": "Run script on user assignments", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] + }, + { + "type": "dict", + "key": "status_update", + "label": "Update status on task action", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "key": "mapping", + "type": "dict-modifiable", + "object_type": { + "type": "list", + "object_type": "text" + } + } + ] + }, + { + "type": "dict", + "key": "status_task_to_parent", + "label": "Sync status from Task to Parent", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "List of parent object types where this is triggered (\"Shot\", \"Asset Build\", etc.). Skipped if list is empty." + }, + { + "type": "list", + "object_type": "text", + "key": "parent_object_types", + "label": "Object types" + }, + { + "key": "parent_status_match_all_task_statuses", + "type": "dict-modifiable", + "label": "Change parent if all tasks match", + "object_type": { + "type": "list", + "object_type": "text" + } + }, + { + "type": "list", + "key": "parent_status_by_task_status", + "label": "Change parent status if a single task matches", + "use_label_wrap": true, + "object_type": { + "type": "dict", + "children": [ + { + "type": "text", + "label": "New parent status", + "key": "new_status" + }, + { + "type": "separator" + }, + { + "type": "list", + "label": "Task status", + "key": "task_statuses", + "object_type": "text" + } + ] + } + } + ] + }, + { + "type": "dict", + "key": "status_task_to_version", + "label": "Sync status from Task to Version", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "dict-modifiable", + "key": "mapping", + "object_type": + { + "type": "list", + "object_type": "text" + } + }, + { + "type": "label", + "label": "Limit status changes to entered asset types. Limitation is ignored if nothing is entered." + }, + { + "type": "list", + "key": "asset_types_filter", + "label": "Asset types (short)", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "status_version_to_task", + "label": "Sync status from Version to Task", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Change Task status based on a changed Version status.
Version's new status on the left will trigger a change of a task status to the first available from the list on right.
- if no status from the list is available it will use the same status as the version." + }, + { + "type": "dict-modifiable", + "key": "mapping", + "object_type": { + "type": "list", + "object_type": "text" + } + }, + { + "type": "separator" + }, + { + "type": "label", + "label": "Disable event if status was changed on specific Asset type." + }, + { + "type": "list", + "label": "Asset types (short)", + "key": "asset_types_to_skip", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "first_version_status", + "label": "Set status on first created version", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "text", + "key": "status", + "label": "Status" + } + ] + }, + { + "type": "dict", + "key": "next_task_update", + "label": "Update status on next task", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Change status on next task by task types order when task status state changed to \"Done\". All tasks with same Task type must be \"Done\"." + }, + { + "type": "label", + "label": "Mapping of next task status changes From -> To." + }, + { + "type": "dict-modifiable", + "key": "mapping", + "object_type": { + "type": "text" + } + }, + { + "type": "separator" + }, + { + "type": "label", + "label": "Status names that are ignored on \"Done\" check (e.g. \"Omitted\")." + }, + { + "type": "list", + "key": "ignored_statuses", + "object_type": "text" + }, + { + "type": "separator" + }, + { + "type": "label", + "label": "Allow to break rule that all tasks with same Task type must be \"Done\" and change statuses with same type tasks ordered by name." + }, + { + "label": "Name sorting", + "type": "boolean", + "key": "name_sorting" + } + ] + } + ] + }, + { + "type": "dict", + "key": "user_handlers", + "label": "User Actions/Events", + "children": [ + { + "type": "dict", + "key": "application_launch_statuses", + "label": "Application - Status change on launch", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Do not change status if current status is:" + }, + { + "type": "list", + "key": "ignored_statuses", + "object_type": "text" + }, + { + "type": "label", + "label": "Change task's status to left side if current task status is in list on right side." + }, + { + "type": "dict-modifiable", + "key": "status_change", + "object_type": { + "type": "list", + "object_type": "text" + } + } + ] + }, + { + "type": "dict", + "key": "create_update_attributes", + "label": "Create/Update Avalon Attributes", + "children": [ + { + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "prepare_project", + "label": "Prepare Project", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "clean_hierarchical_attr", + "label": "Clean hierarchical custom attributes", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "delete_asset_subset", + "label": "Delete Asset/Subsets", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "delete_old_versions", + "label": "Delete old versions", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "delivery_action", + "label": "Delivery", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "store_thubmnail_to_avalon", + "label": "Store Thumbnails to avalon", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "job_killer", + "label": "Job Killer", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "sync_to_avalon_local", + "label": "Sync to avalon (local) - For development", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" + } + ] + }, + { + "type": "dict", + "key": "seed_project", + "label": "Seed Debug Project", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "role_list", + "label": "Roles", + "object_type": "text" + } + ] + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "publish", + "label": "Publish plugins", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "IntegrateFtrackNote", + "label": "IntegrateFtrackNote", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "text", + "key": "note_with_intent_template", + "label": "Note with intent template" + }, + { + "type": "list", + "object_type": "text", + "key": "note_labels", + "label": "Note labels" + } + ] + }, + + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "ValidateFtrackAttributes", + "label": "ValidateFtrackAttributes", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "raw-json", + "key": "ftrack_custom_attributes", + "label": "Custom attributes to validate" + } + ] + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_global.json b/pype/settings/entities/schemas/projects_schema/schema_project_global.json new file mode 100644 index 0000000000..ab9b56115d --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_global.json @@ -0,0 +1,33 @@ +{ + "type": "dict", + "collapsable": true, + "key": "global", + "label": "Global", + "is_file": true, + "children": [ + { + "type": "schema", + "name": "schema_global_publish" + }, + { + "type": "schema", + "name": "schema_global_tools" + }, + + { + "type": "collapsible-wrap", + "label": "Project Folder Structure", + "children": [ + { + "type": "raw-json", + "key": "project_folder_structure" + } + ] + }, + + { + "type": "schema", + "name": "schema_project_syncserver" + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_harmony.json b/pype/settings/entities/schemas/projects_schema/schema_project_harmony.json new file mode 100644 index 0000000000..92ad39ac2c --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_harmony.json @@ -0,0 +1,36 @@ +{ + "type": "dict", + "collapsable": true, + "key": "harmony", + "label": "Harmony", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "publish", + "label": "Publish plugins", + "children": [] + }, + { + "type": "dict", + "collapsable": true, + "key": "general", + "label": "General", + "children": [ + { + "type": "list", + "key": "skip_resolution_check", + "object_type": "text", + "label": "Skip Resolution Check for Tasks" + }, + { + "type": "list", + "key": "skip_timelines_check", + "object_type": "text", + "label": "Skip Timeliene Check for Tasks" + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_hiero.json b/pype/settings/entities/schemas/projects_schema/schema_project_hiero.json new file mode 100644 index 0000000000..b6276ccf9e --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_hiero.json @@ -0,0 +1,172 @@ +{ + "type": "dict", + "collapsable": true, + "key": "hiero", + "label": "Hiero", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "create", + "label": "Create plugins", + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "CreateShotClip", + "label": "Create Shot Clip", + "is_group": true, + "children": [ + { + "type": "collapsible-wrap", + "label": "Shot Hierarchy And Rename Settings", + "collapsable": false, + "children": [ + { + "type": "text", + "key": "hierarchy", + "label": "Shot parent hierarchy" + }, + { + "type": "boolean", + "key": "clipRename", + "label": "Rename clips" + }, + { + "type": "text", + "key": "clipName", + "label": "Clip name template" + }, + { + "type": "number", + "key": "countFrom", + "label": "Count sequence from" + }, + { + "type": "number", + "key": "countSteps", + "label": "Stepping number" + } + ] + }, + { + "type": "collapsible-wrap", + "label": "Shot Template Keywords", + "collapsable": false, + "children": [ + { + "type": "text", + "key": "folder", + "label": "{folder}" + }, + { + "type": "text", + "key": "episode", + "label": "{episode}" + }, + { + "type": "text", + "key": "sequence", + "label": "{sequence}" + }, + { + "type": "text", + "key": "track", + "label": "{track}" + }, + { + "type": "text", + "key": "shot", + "label": "{shot}" + } + ] + }, + { + "type": "collapsible-wrap", + "label": "Vertical Synchronization Of Attributes", + "collapsable": false, + "children": [ + { + "type": "boolean", + "key": "vSyncOn", + "label": "Enable Vertical Sync" + } + ] + }, + { + "type": "collapsible-wrap", + "label": "Shot Attributes", + "collapsable": false, + "children": [ + { + "type": "number", + "key": "workfileFrameStart", + "label": "Workfiles Start Frame" + }, + { + "type": "number", + "key": "handleStart", + "label": "Handle start (head)" + }, + { + "type": "number", + "key": "handleEnd", + "label": "Handle end (tail)" + } + ] + } + ] + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "publish", + "label": "Publish plugins", + "children": [ + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "CollectInstanceVersion", + "label": "Collect Instance Version", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "ExtractReviewCutUpVideo", + "label": "Extract Review Cut Up Video", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "object_type": "text", + "key": "tags_addition", + "label": "Tags addition" + } + ] + } + ] + }, + { + "type": "schema", + "name": "schema_publish_gui_filter" + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_maya.json b/pype/settings/entities/schemas/projects_schema/schema_project_maya.json new file mode 100644 index 0000000000..069ae3c977 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_maya.json @@ -0,0 +1,29 @@ +{ + "type": "dict", + "collapsable": true, + "key": "maya", + "label": "Maya", + "is_file": true, + "children": [ + { + "type": "schema", + "name": "schema_maya_capture" + }, + { + "type": "schema", + "name": "schema_maya_publish" + }, + { + "type": "schema", + "name": "schema_maya_load" + }, + { + "type": "schema", + "name": "schema_workfile_build" + }, + { + "type": "schema", + "name": "schema_publish_gui_filter" + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json b/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json new file mode 100644 index 0000000000..7a6960bcbd --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json @@ -0,0 +1,193 @@ +{ + "type": "dict", + "collapsable": true, + "key": "nuke", + "label": "Nuke", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "create", + "label": "Create plugins", + "children": [ + { + "type": "dict", + "collapsable": false, + "key": "CreateWriteRender", + "label": "CreateWriteRender", + "is_group": true, + "children": [ + { + "type": "text", + "key": "fpath_template", + "label": "Path template" + } + ] + }, + { + "type": "dict", + "collapsable": false, + "key": "CreateWritePrerender", + "label": "CreateWritePrerender", + "is_group": true, + "children": [ + { + "type": "text", + "key": "fpath_template", + "label": "Path template" + } + ] + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "publish", + "label": "Publish plugins", + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "PreCollectNukeInstances", + "label": "PreCollectNukeInstances", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "sync_workfile_version", + "label": "Sync Version from workfile" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "ExtractThumbnail", + "label": "ExtractThumbnail", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "raw-json", + "key": "nodes", + "label": "Nodes" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "ValidateKnobs", + "label": "ValidateKnobs", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "raw-json", + "key": "knobs", + "label": "Knobs" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "ExtractReviewDataLut", + "label": "ExtractReviewDataLut", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "ExtractReviewDataMov", + "label": "ExtractReviewDataMov", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "viewer_lut_raw", + "label": "Viewer LUT raw" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "ExtractSlateFrame", + "label": "ExtractSlateFrame", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "viewer_lut_raw", + "label": "Viewer LUT raw" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "NukeSubmitDeadline", + "label": "NukeSubmitDeadline", + "is_group": true, + "children": [ + { + "type": "number", + "key": "deadline_priority", + "label": "deadline_priority" + }, + { + "type": "text", + "key": "deadline_pool", + "label": "deadline_pool" + }, + { + "type": "text", + "key": "deadline_pool_secondary", + "label": "deadline_pool_secondary" + }, + { + "type": "number", + "key": "deadline_chunk_size", + "label": "deadline_chunk_size" + } + ] + } + ] + }, + { + "type": "schema", + "name": "schema_workfile_build" + }, + { + "type": "schema", + "name": "schema_publish_gui_filter" + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_resolve.json b/pype/settings/entities/schemas/projects_schema/schema_project_resolve.json new file mode 100644 index 0000000000..fb9b9b7a0a --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_resolve.json @@ -0,0 +1,124 @@ +{ + "type": "dict", + "collapsable": true, + "key": "resolve", + "label": "DaVinci Resolve", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "create", + "label": "Creator plugins", + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "CreateShotClip", + "label": "Create Shot Clip", + "is_group": true, + "children": [ + { + "type": "collapsible-wrap", + "label": "Shot Hierarchy And Rename Settings", + "collapsable": false, + "children": [ + { + "type": "text", + "key": "hierarchy", + "label": "Shot parent hierarchy" + }, + { + "type": "boolean", + "key": "clipRename", + "label": "Rename clips" + }, + { + "type": "text", + "key": "clipName", + "label": "Clip name template" + }, + { + "type": "number", + "key": "countFrom", + "label": "Count sequence from" + }, + { + "type": "number", + "key": "countSteps", + "label": "Stepping number" + } + ] + }, + { + "type": "collapsible-wrap", + "label": "Shot Template Keywords", + "collapsable": false, + "children": [ + { + "type": "text", + "key": "folder", + "label": "{folder}" + }, + { + "type": "text", + "key": "episode", + "label": "{episode}" + }, + { + "type": "text", + "key": "sequence", + "label": "{sequence}" + }, + { + "type": "text", + "key": "track", + "label": "{track}" + }, + { + "type": "text", + "key": "shot", + "label": "{shot}" + } + ] + }, + { + "type": "collapsible-wrap", + "label": "Vertical Synchronization Of Attributes", + "collapsable": false, + "children": [ + { + "type": "boolean", + "key": "vSyncOn", + "label": "Enable Vertical Sync" + } + ] + }, + { + "type": "collapsible-wrap", + "label": "Shot Attributes", + "collapsable": false, + "children": [ + { + "type": "number", + "key": "workfileFrameStart", + "label": "Workfiles Start Frame" + }, + { + "type": "number", + "key": "handleStart", + "label": "Handle start (head)" + }, + { + "type": "number", + "key": "handleEnd", + "label": "Handle end (tail)" + } + ] + } + ] + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_standalonepublisher.json b/pype/settings/entities/schemas/projects_schema/schema_project_standalonepublisher.json new file mode 100644 index 0000000000..40b27f766f --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_standalonepublisher.json @@ -0,0 +1,93 @@ +{ + "type": "dict", + "collapsable": true, + "key": "standalonepublisher", + "label": "Standalone Publisher", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "publish", + "label": "Publish plugins", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "ExtractThumbnailSP", + "label": "ExtractThumbnailSP", + "is_group": true, + "children": [ + { + "type": "dict", + "collapsable": false, + "key": "ffmpeg_args", + "label": "ffmpeg_args", + "children": [ + { + "type": "list", + "object_type": "text", + "key": "input", + "label": "input" + }, + { + "type": "list", + "object_type": "text", + "key": "output", + "label": "output" + } + ] + } + ] + } + ] + }, + { + "type": "dict-modifiable", + "collapsable": true, + "key": "create", + "label": "Creator plugins", + "collapsable_key": true, + "is_file": true, + "object_type": { + "type": "dict", + "children": [ + { + "type": "text", + "key": "name", + "label": "Name" + }, + { + "type": "text", + "key": "label", + "label": "Label" + }, + { + "type": "text", + "key": "family", + "label": "Family" + }, + { + "type": "text", + "key": "icon", + "label": "Icon" + }, + { + "type": "list", + "key": "defaults", + "label": "Defaults", + "object_type": { + "type": "text" + } + }, + { + "type": "text", + "key": "help", + "label": "Help" + } + ] + } + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_syncserver.json b/pype/settings/entities/schemas/projects_schema/schema_project_syncserver.json new file mode 100644 index 0000000000..396e4ca2dc --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_syncserver.json @@ -0,0 +1,76 @@ +{ + "type": "dict", + "key": "sync_server", + "label": "Sync Server (currently unused)", + "collapsable": true, + "checkbox_key": "enabled", + "is_file": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "dict", + "key": "config", + "label": "Config", + "collapsable": true, + "children": [ + + { + "type": "text", + "key": "local_id", + "label": "Local ID" + }, + { + "type": "text", + "key": "retry_cnt", + "label": "Retry Count" + }, + { + "type": "text", + "key": "loop_delay", + "label": "Loop Delay" + }, + { + "type": "text", + "key": "active_site", + "label": "Active Site" + }, + { + "type": "text", + "key": "remote_site", + "label": "Remote Site" + } + ] + }, { + "type": "dict-modifiable", + "collapsable": true, + "key": "sites", + "label": "Sites", + "collapsable_key": false, + "is_file": true, + "object_type": + { + "type": "dict", + "children": [ + { + "type": "text", + "key": "provider", + "label": "Provider" + }, + { + "type": "text", + "key": "credentials_url", + "label": "Credentials url" + }, + { + "type": "text", + "key": "root", + "label": "Root" + }] + } + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_unreal.json b/pype/settings/entities/schemas/projects_schema/schema_project_unreal.json new file mode 100644 index 0000000000..392289296a --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schema_project_unreal.json @@ -0,0 +1,27 @@ +{ + "type": "dict", + "collapsable": true, + "key": "unreal", + "label": "Unreal Engine", + "is_file": true, + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "project_setup", + "label": "Project Setup", + "children": [ + { + "type": "boolean", + "key": "dev_mode", + "label": "Dev mode" + }, + { + "type": "boolean", + "key": "install_unreal_python_engine", + "label": "Install unreal python engine" + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json new file mode 100644 index 0000000000..b045ef978b --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json @@ -0,0 +1,79 @@ +{ + "type": "dict", + "collapsable": true, + "key": "attributes", + "label": "Attributes", + "is_file": true, + "children": [ + { + "type": "number", + "key": "fps", + "label": "Frame Rate" + }, + { + "type": "number", + "key": "frameStart", + "label": "Frame Start" + }, + { + "type": "number", + "key": "frameEnd", + "label": "Frame End" + }, + { + "type": "number", + "key": "clipIn", + "label": "Clip In" + }, + { + "type": "number", + "key": "clipOut", + "label": "Clip Out" + }, + { + "type": "number", + "key": "handleStart", + "label": "Handle Start" + }, + { + "type": "number", + "key": "handleEnd", + "label": "Handle End" + }, + { + "type": "number", + "key": "resolutionWidth", + "label": "Resolution Width" + }, + { + "type": "number", + "key": "resolutionHeight", + "label": "Resolution Height" + }, + { + "type": "number", + "key": "pixelAspect", + "label": "Pixel Aspect Ratio" + }, + { + "type": "enum", + "key": "applications", + "label": "Applications", + "multiselection": true, + "enum_items": [ + { "maya_2020": "Maya 2020" }, + { "nuke_12.2": "Nuke 12.2" }, + { "hiero_12.2": "Hiero 12.2" }, + { "houdini_18": "Houdini 18" }, + { "blender_2.91": "Blender 2.91" }, + { "aftereffects_2021": "After Effects 2021" } + ] + }, + { + "type": "dict-modifiable", + "key": "task_short_names", + "label": "Task short names (by Task type)", + "object_type": "text" + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json new file mode 100644 index 0000000000..0032e3de06 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json @@ -0,0 +1,353 @@ +{ + "type": "dict", + "key": "imageio", + "label": "Color Management and Output Formats", + "is_file": true, + "children": [ + { + "key": "hiero", + "type": "dict", + "label": "Hiero", + "children": [ + { + "key": "workfile", + "type": "dict", + "label": "Workfile", + "collapsable": false, + "children": [ + { + "type": "form", + "children": [ + { + "type": "enum", + "key": "ocioConfigName", + "label": "OpenColorIO Config", + "enum_items": [ + { + "nuke-default": "nuke-default" + }, + { + "aces_1.0.3": "aces_1.0.3" + }, + { + "aces_1.1": "aces_1.1" + }, + { + "custom": "custom" + } + ] + }, + { + "type": "path-widget", + "key": "ocioconfigpath", + "label": "Custom OCIO path", + "multiplatform": true, + "multipath": true + }, + { + "type": "text", + "key": "workingSpace", + "label": "Working Space" + }, + { + "type": "text", + "key": "sixteenBitLut", + "label": "16 Bit Files" + }, + { + "type": "text", + "key": "eightBitLut", + "label": "8 Bit Files" + }, + { + "type": "text", + "key": "floatLut", + "label": "Floating Point Files" + }, + { + "type": "text", + "key": "logLut", + "label": "Log Files" + }, + { + "type": "text", + "key": "viewerLut", + "label": "Viewer" + }, + { + "type": "text", + "key": "thumbnailLut", + "label": "Thumbnails" + } + ] + } + ] + }, + { + "key": "regexInputs", + "type": "dict", + "label": "Colorspace on Inputs by regex detection", + "collapsable": true, + "children": [ + { + "type": "list", + "key": "inputs", + "object_type": { + "type": "dict", + "children": [ + { + "type": "text", + "key": "regex", + "label": "Regex" + }, + { + "type": "text", + "key": "colorspace", + "label": "Colorspace" + } + ] + } + } + ] + } + ] + }, + { + "key": "nuke", + "type": "dict", + "label": "Nuke", + "children": [ + { + "key": "workfile", + "type": "dict", + "label": "Workfile", + "collapsable": false, + "is_group": true, + "children": [ + { + "type": "form", + "children": [ + { + "type": "enum", + "key": "colorManagement", + "label": "color management", + "enum_items": [ + { + "Nuke": "Nuke" + }, + { + "OCIO": "OCIO" + } + ] + }, + { + "type": "enum", + "key": "OCIO_config", + "label": "OpenColorIO Config", + "enum_items": [ + { + "nuke-default": "nuke-default" + }, + { + "spi-vfx": "spi-vfx" + }, + { + "spi-anim": "spi-anim" + }, + { + "aces_1.0.3": "aces_0.1.1" + }, + { + "aces_1.0.3": "aces_0.7.1" + }, + { + "aces_1.0.3": "aces_1.0.1" + }, + { + "aces_1.0.3": "aces_1.0.3" + }, + { + "aces_1.1": "aces_1.1" + }, + { + "custom": "custom" + } + ] + }, + { + "type": "path-widget", + "key": "customOCIOConfigPath", + "label": "Custom OCIO config path", + "multiplatform": true, + "multipath": true + }, + { + "type": "text", + "key": "workingSpaceLUT", + "label": "Working Space" + }, + { + "type": "text", + "key": "monitorLut", + "label": "monitor" + }, + { + "type": "text", + "key": "int8Lut", + "label": "8-bit files" + }, + { + "type": "text", + "key": "int16Lut", + "label": "16-bit files" + }, + { + "type": "text", + "key": "logLut", + "label": "log files" + }, + { + "type": "text", + "key": "floatLut", + "label": "float files" + } + ] + } + ] + }, + { + "key": "nodes", + "type": "dict", + "label": "Nodes", + "collapsable": true, + "is_group": true, + "children": [ + { + "key": "requiredNodes", + "type": "list", + "label": "Required Nodes", + "object_type": { + "type": "dict", + "children": [ + { + "type": "list", + "key": "plugins", + "label": "Used in plugins", + "object_type": { + "type": "text", + "key": "pluginClass", + "label": "Plugin Class" + } + }, + { + "type": "text", + "key": "nukeNodeClass", + "label": "Nuke Node Class" + }, + { + "type": "splitter" + }, + { + "key": "knobs", + "label": "Knobs", + "type": "list", + "object_type": { + "type": "dict", + "children": [ + { + "type": "text", + "key": "name", + "label": "Name" + }, + { + "type": "text", + "key": "value", + "label": "Value" + } + ] + } + } + ] + } + }, + { + "type": "list", + "key": "customNodes", + "label": "Custom Nodes", + "object_type": { + "type": "dict", + "children": [ + { + "type": "list", + "key": "plugins", + "label": "Used in plugins", + "object_type": { + "type": "text", + "key": "pluginClass", + "label": "Plugin Class" + } + }, + { + "type": "text", + "key": "nukeNodeClass", + "label": "Nuke Node Class" + }, + { + "type": "splitter" + }, + { + "key": "knobs", + "label": "Knobs", + "type": "list", + "object_type": { + "type": "dict", + "children": [ + { + "type": "text", + "key": "name", + "label": "Name" + }, + { + "type": "text", + "key": "value", + "label": "Value" + } + ] + } + } + ] + } + } + ] + }, + { + "key": "regexInputs", + "type": "dict", + "label": "Colorspace on Inputs by regex detection", + "collapsable": true, + "children": [ + { + "type": "list", + "key": "inputs", + "object_type": { + "type": "dict", + "children": [ + { + "type": "text", + "key": "regex", + "label": "Regex" + }, + { + "type": "text", + "key": "colorspace", + "label": "Colorspace" + } + ] + } + } + ] + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json new file mode 100644 index 0000000000..1f545f14be --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json @@ -0,0 +1,135 @@ +{ + "type": "dict", + "collapsable": true, + "key": "templates", + "label": "Templates", + "collapsable_key": true, + "is_file": true, + "children": [ + { + "type": "number", + "key": "version_padding", + "label": "Version Padding" + }, + { + "type": "text", + "key": "version", + "label": "Version" + }, + { + "type": "number", + "key": "frame_padding", + "label": "Frame Padding" + }, + { + "type": "text", + "key": "frame", + "label": "Frame" + }, + { + "type": "dict", + "key": "work", + "label": "Work", + "children": [ + { + "type": "text", + "key": "folder", + "label": "Folder" + }, + { + "type": "text", + "key": "file", + "label": "File" + }, + { + "type": "text", + "key": "path", + "label": "Path" + } + ] + }, + { + "type": "dict", + "key": "render", + "label": "Render", + "children": [ + { + "type": "text", + "key": "folder", + "label": "Folder" + }, + { + "type": "text", + "key": "file", + "label": "File" + }, + { + "type": "text", + "key": "path", + "label": "Path" + } + ] + }, + { + "type": "dict", + "key": "publish", + "label": "Publish", + "children": [ + { + "type": "text", + "key": "folder", + "label": "Folder" + }, + { + "type": "text", + "key": "file", + "label": "File" + }, + { + "type": "text", + "key": "path", + "label": "Path" + }, + { + "type": "text", + "key": "thumbnail", + "label": "Thumbnail" + } + ] + }, + { + "type": "dict", + "key": "master", + "label": "Master", + "children": [ + { + "type": "text", + "key": "folder", + "label": "Folder" + }, + { + "type": "text", + "key": "file", + "label": "File" + }, + { + "type": "text", + "key": "path", + "label": "Path" + } + ] + }, + { + "type": "dict-modifiable", + "key": "delivery", + "label": "Delivery", + "object_type": "text" + }, + { + "type": "dict-modifiable", + "key": "other", + "label": "Other", + "object_type": "text" + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json new file mode 100644 index 0000000000..5d17830b92 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json @@ -0,0 +1,407 @@ +{ + "type": "dict", + "collapsable": true, + "key": "publish", + "label": "Publish plugins", + "children": [ + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "IntegrateMasterVersion", + "label": "IntegrateMasterVersion", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "checkbox_key": "enabled", + "key": "ExtractJpegEXR", + "label": "ExtractJpegEXR", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "dict", + "key": "ffmpeg_args", + "children": [ + { + "type": "list", + "object_type": "text", + "key": "input", + "label": "FFmpeg input arguments" + }, + { + "type": "list", + "object_type": "text", + "key": "output", + "label": "FFmpeg output arguments" + } + ] + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "ExtractReview", + "label": "ExtractReview", + "checkbox_key": "enabled", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "list", + "key": "profiles", + "label": "Profiles", + "object_type": { + "type": "dict", + "children": [ + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + }, + { + "key": "hosts", + "label": "Hosts", + "type": "list", + "object_type": "text" + }, + { + "type": "splitter" + }, + { + "key": "outputs", + "label": "Output Definitions", + "type": "dict-modifiable", + "highlight_content": true, + "object_type": { + "type": "dict", + "children": [ + { + "key": "ext", + "label": "Output extension", + "type": "text" + }, + { + "key": "tags", + "label": "Tags", + "type": "enum", + "multiselection": true, + "enum_items": [ + { + "burnin": "Add burnins" + }, + { + "ftrackreview": "Add to Ftrack" + }, + { + "delete": "Delete output" + }, + { + "slate-frame": "Add slate frame" + }, + { + "no-hnadles": "Skip handle frames" + } + ] + }, + { + "key": "ffmpeg_args", + "label": "FFmpeg arguments", + "type": "dict", + "highlight_content": true, + "children": [ + { + "key": "video_filters", + "label": "Video filters", + "type": "list", + "object_type": "text" + }, + { + "type": "splitter" + }, + { + "key": "audio_filters", + "label": "Audio filters", + "type": "list", + "object_type": "text" + }, + { + "type": "splitter" + }, + { + "key": "input", + "label": "Input arguments", + "type": "list", + "object_type": "text" + }, + { + "type": "splitter" + }, + { + "key": "output", + "label": "Output arguments", + "type": "list", + "object_type": "text" + } + ] + }, + { + "key": "filter", + "label": "Additional output filtering", + "type": "dict", + "highlight_content": true, + "children": [ + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + } + ] + } + ] + } + } + ] + } + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "ExtractBurnin", + "label": "ExtractBurnin", + "checkbox_key": "enabled", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "dict", + "collapsable": true, + "key": "options", + "label": "Burnin formating options", + "children": [ + { + "type": "number", + "key": "font_size", + "label": "Font size" + }, + { + "type": "number", + "key": "opacity", + "label": "Font opacity" + }, + { + "type": "number", + "key": "bg_opacity", + "label": "Background opacity" + }, + { + "type": "number", + "key": "x_offset", + "label": "X Offset" + }, + { + "type": "number", + "key": "y_offset", + "label": "Y Offset" + }, + { + "type": "number", + "key": "bg_padding", + "label": "Padding aroung text" + }, + { + "type": "splitter" + } + ] + }, + + { + "type": "list", + "key": "profiles", + "label": "Profiles", + "object_type": { + "type": "dict", + "children": [ + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + }, + { + "key": "hosts", + "label": "Hosts", + "type": "list", + "object_type": "text" + }, + { + "type": "splitter" + }, + { + "key": "burnins", + "label": "Burnins", + "type": "dict-modifiable", + "highlight_content": true, + "collapsable": false, + "object_type": { + "type": "dict", + "children": [ + { + "key": "TOP_LEFT", + "label": "Top Left", + "type": "text" + }, + { + "key": "TOP_CENTERED", + "label": "Top Centered", + "type": "text" + }, + { + "key": "TOP_RIGHT", + "label": "top Right", + "type": "text" + }, + { + "key": "BOTTOM_LEFT", + "label": "Bottom Left", + "type": "text" + }, + { + "key": "BOTTOM_CENTERED", + "label": "Bottom Centered", + "type": "text" + }, + { + "key": "BOTTOM_RIGHT", + "label": "BottomRight", + "type": "text" + } + ] + } + } + ] + } + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "IntegrateAssetNew", + "label": "IntegrateAssetNew", + "is_group": true, + "children": [ + { + "type": "raw-json", + "key": "template_name_profiles", + "label": "template_name_profiles" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "ProcessSubmittedJobOnFarm", + "label": "ProcessSubmittedJobOnFarm", + "checkbox_key": "enabled", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "text", + "key": "deadline_department", + "label": "Deadline department" + }, + { + "type": "text", + "key": "deadline_pool", + "label": "Deadline Pool" + }, + { + "type": "text", + "key": "deadline_group", + "label": "Deadline Group" + }, + { + "type": "number", + "key": "deadline_chunk_size", + "label": "Deadline Chunk Size" + }, + { + "type": "number", + "key": "deadline_priority", + "label": "Deadline Priotity" + }, + { + "type": "dict", + "key": "aov_filter", + "label": "Reviewable subsets filter", + "children": [ + { + "type": "list", + "key": "maya", + "label": "Maya", + "object_type": { + "type": "text" + } + }, + { + "type": "list", + "key": "nuke", + "label": "Nuke", + "object_type": { + "type": "text" + } + }, + { + "type": "list", + "key": "aftereffects", + "label": "After Effects", + "object_type": { + "type": "text" + } + }, + { + "type": "list", + "key": "celaction", + "label": "Celaction", + "object_type": { + "type": "text" + } + } + ] + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json new file mode 100644 index 0000000000..d89477edd1 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json @@ -0,0 +1,77 @@ +{ + "type": "dict", + "collapsable": true, + "key": "tools", + "label": "Tools", + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "creator", + "label": "Creator", + "children": [ + { + "type": "dict-modifiable", + "collapsable": false, + "key": "families_smart_select", + "label": "Families smart select", + "object_type": { + "type": "list", + "object_type": "text" + } + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "Workfiles", + "label": "Workfiles", + "children": [ + { + "type": "list", + "key": "last_workfile_on_startup", + "label": "Open last workfiles on launch", + "is_group": true, + "use_label_wrap": true, + "object_type": { + "type": "dict", + "children": [ + { + "key": "hosts", + "label": "Hosts", + "type": "list", + "object_type": "text" + }, + { + "key": "tasks", + "label": "Tasks", + "type": "list", + "object_type": "text" + }, + { + "type": "splitter" + }, + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] + } + }, + { + "type": "dict-modifiable", + "collapsable": true, + "key": "sw_folders", + "label": "Extra task folders", + "is_group": true, + "object_type": { + "type": "list", + "object_type": "text" + } + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json new file mode 100644 index 0000000000..ba7cf4b525 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -0,0 +1,595 @@ +{ + "type": "collapsible-wrap", + "label": "Collapsible Wrapper without key", + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "capture", + "label": "Maya Playblast settings", + "is_file": true, + "children": [ + { + "type": "dict", + "key": "Codec", + "children": [ + { + "type": "label", + "label": "Codec" + }, + { + "type": "text", + "key": "compression", + "label": "Compression type" + }, + { + "type": "text", + "key": "format", + "label": "Data format" + }, + { + "type": "number", + "key": "quality", + "label": "Quality", + "decimal": 0, + "minimum": 0, + "maximum": 100 + }, + + { + "type": "splitter" + } + ] + }, + { + "type": "dict", + "key": "Display Options", + "children": [ + { + "type": "label", + "label": "Display Options" + }, + { + "type": "list-strict", + "key": "background", + "label": "Background Color: ", + "object_types": [ + { + "label": "Red", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + }, + { + "label": "Green", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + }, + { + "label": "Blue", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + } + ] + }, + { + "type": "list-strict", + "key": "backgroundBottom", + "label": "Background Bottom: ", + "object_types": [ + { + "label": "Red", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + }, + { + "label": "Green", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + }, + { + "label": "Blue", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + } + ] + }, + { + "type": "list-strict", + "key": "backgroundTop", + "label": "Background Top: ", + "object_types": [ + { + "label": "Red", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + }, + { + "label": "Green", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + }, + { + "label": "Blue", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + } + ] + }, + { + "type": "boolean", + "key": "override_display", + "label": "Override display options" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "dict", + "key": "Generic", + "children": [ + { + "type": "label", + "label": "Generic" + }, + { + "type": "boolean", + "key": "isolate_view", + "label": " Isolate view" + }, + { + "type": "boolean", + "key": "off_screen", + "label": " Off Screen" + } + ] + }, + { + "type": "dict", + "key": "IO", + "children": [ + { + "type": "label", + "label": "IO" + }, + { + "type": "text", + "key": "name", + "label": "Name" + }, + { + "type": "boolean", + "key": "open_finished", + "label": "Open finished" + }, + { + "type": "boolean", + "key": "raw_frame_numbers", + "label": "Raw frame numbers" + }, + { + "type": "list", + "key": "recent_playblasts", + "label": "Recent Playblasts", + "object_type": "text" + }, + { + "type": "boolean", + "key": "save_file", + "label": "Save file" + } + ] + }, + { + "type": "dict", + "key": "PanZoom", + "children": [ + { + "type": "boolean", + "key": "pan_zoom", + "label": " Pan Zoom" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "dict", + "key": "Renderer", + "children": [ + { + "type": "label", + "label": "Renderer" + }, + { + "type": "text", + "key": "rendererName", + "label": " Renderer name" + } + ] + }, + { + "type": "dict", + "key": "Resolution", + "children": [ + { + "type": "splitter" + }, + { + "type": "label", + "label": "Resolution" + }, + { + "type": "number", + "key": "width", + "label": " Width", + "decimal": 0, + "minimum": 0, + "maximum": 99999 + }, + { + "type": "number", + "key": "height", + "label": "Height", + "decimal": 0, + "minimum": 0, + "maximum": 99999 + }, + { + "type": "number", + "key": "percent", + "label": "percent", + "decimal": 1, + "minimum": 0, + "maximum": 200 + }, + { + "type": "text", + "key": "mode", + "label": "Mode" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "dict", + "key": "Time Range", + "children": [ + { + "type": "label", + "label": "Time Range" + }, + { + "type": "number", + "key": "start_frame", + "label": " Start frame", + "decimal": 0, + "minimum": 0, + "maximum": 999999 + }, + { + "type": "number", + "key": "end_frame", + "label": "End frame", + "decimal": 0, + "minimum": 0, + "maximum": 999999 + }, + { + "type": "text", + "key": "frame", + "label": "Frame" + }, + { + "type": "text", + "key": "time", + "label": "Time" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "Viewport Options", + "label": "Viewport Options", + "children": [ + { + "type": "boolean", + "key": "cameras", + "label": "cameras" + }, + { + "type": "boolean", + "key": "clipGhosts", + "label": "clipGhosts" + }, + { + "type": "boolean", + "key": "controlVertices", + "label": "controlVertices" + }, + { + "type": "boolean", + "key": "deformers", + "label": "deformers" + }, + { + "type": "boolean", + "key": "dimensions", + "label": "dimensions" + }, + { + "type": "number", + "key": "displayLights", + "label": "displayLights", + "decimal": 0, + "minimum": 0, + "maximum": 10 + }, + { + "type": "boolean", + "key": "dynamicConstraints", + "label": "dynamicConstraints" + }, + { + "type": "boolean", + "key": "dynamics", + "label": "dynamics" + }, + { + "type": "boolean", + "key": "fluids", + "label": "fluids" + }, + { + "type": "boolean", + "key": "follicles", + "label": "follicles" + }, + { + "type": "boolean", + "key": "gpuCacheDisplayFilter", + "label": "gpuCacheDisplayFilter" + }, + { + "type": "boolean", + "key": "greasePencils", + "label": "greasePencils" + }, + { + "type": "boolean", + "key": "grid", + "label": "grid" + }, + { + "type": "boolean", + "key": "hairSystems", + "label": "hairSystems" + }, + { + "type": "boolean", + "key": "handles", + "label": "handles" + }, + { + "type": "boolean", + "key": "high_quality", + "label": "high_quality" + }, + { + "type": "boolean", + "key": "hud", + "label": "hud" + }, + { + "type": "boolean", + "key": "hulls", + "label": "hulls" + }, + { + "type": "boolean", + "key": "ikHandles", + "label": "ikHandles" + }, + { + "type": "boolean", + "key": "imagePlane", + "label": "imagePlane" + }, + { + "type": "boolean", + "key": "joints", + "label": "joints" + }, + { + "type": "boolean", + "key": "lights", + "label": "lights" + }, + { + "type": "boolean", + "key": "locators", + "label": "locators" + }, + { + "type": "boolean", + "key": "manipulators", + "label": "manipulators" + }, + { + "type": "boolean", + "key": "motionTrails", + "label": "motionTrails" + }, + { + "type": "boolean", + "key": "nCloths", + "label": "nCloths" + }, + { + "type": "boolean", + "key": "nParticles", + "label": "nParticles" + }, + { + "type": "boolean", + "key": "nRigids", + "label": "nRigids" + }, + { + "type": "boolean", + "key": "nurbsCurves", + "label": "nurbsCurves" + }, + { + "type": "boolean", + "key": "nurbsSurfaces", + "label": "nurbsSurfaces" + }, + { + "type": "boolean", + "key": "override_viewport_options", + "label": "override_viewport_options" + }, + { + "type": "boolean", + "key": "particleInstancers", + "label": "particleInstancers" + }, + { + "type": "boolean", + "key": "pivots", + "label": "pivots" + }, + { + "type": "boolean", + "key": "planes", + "label": "planes" + }, + { + "type": "boolean", + "key": "pluginShapes", + "label": "pluginShapes" + }, + { + "type": "boolean", + "key": "polymeshes", + "label": "polymeshes" + }, + { + "type": "boolean", + "key": "shadows", + "label": "shadows" + }, + { + "type": "boolean", + "key": "strokes", + "label": "strokes" + }, + { + "type": "boolean", + "key": "subdivSurfaces", + "label": "subdivSurfaces" + }, + { + "type": "boolean", + "key": "textures", + "label": "textures" + }, + { + "type": "boolean", + "key": "twoSidedLighting", + "label": "twoSidedLighting" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "Camera Options", + "label": "Camera Options", + "children": [ + { + "type": "boolean", + "key": "displayGateMask", + "label": "displayGateMask" + }, + { + "type": "boolean", + "key": "displayResolution", + "label": "displayResolution" + }, + { + "type": "boolean", + "key": "displayFilmGate", + "label": "displayFilmGate" + }, + { + "type": "boolean", + "key": "displayFieldChart", + "label": "displayFieldChart" + }, + { + "type": "boolean", + "key": "displaySafeAction", + "label": "displaySafeAction" + }, + { + "type": "boolean", + "key": "displaySafeTitle", + "label": "displaySafeTitle" + }, + { + "type": "boolean", + "key": "displayFilmPivot", + "label": "displayFilmPivot" + }, + { + "type": "boolean", + "key": "displayFilmOrigin", + "label": "displayFilmOrigin" + }, + { + "type": "number", + "key": "overscan", + "label": "overscan", + "decimal": 1, + "minimum": 0, + "maximum": 10 + } + ] + } + ] + }, + { + "type": "dict-modifiable", + "key": "ext_mapping", + "label": "Extension Mapping", + "object_type": { + "type": "text" + } + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json new file mode 100644 index 0000000000..5aec3715bd --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json @@ -0,0 +1,156 @@ +{ + "type": "dict", + "collapsable": true, + "key": "load", + "label": "Loader plugins", + "children": [ + { + "type": "dict", + "collapsable": true, + "key": "colors", + "label": "Loaded Subsets Outliner Colors", + "children": [ + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Model", + "name": "model" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Rig", + "name": "rig" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Pointcache", + "name": "pointcache" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Animation", + "name": "animation" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Arnold Standin", + "name": "ass" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Camera", + "name": "camera" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "FBX", + "name": "fbx" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Maya Scene", + "name": "mayaAscii" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Set Dress", + "name": "setdress" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Layout", + "name": "layout" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "VDB Cache", + "name": "vdbcache" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Vray Proxy", + "name": "vrayproxy" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Yeti Cache", + "name": "yeticache" + } + ] + }, + { + "type": "schema_template", + "name": "template_color", + "template_data": [ + { + "label": "Yeti Rig", + "name": "yetiRig" + } + ] + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json new file mode 100644 index 0000000000..d1de128934 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -0,0 +1,214 @@ +{ + "type": "dict", + "collapsable": true, + "key": "publish", + "label": "Publish plugins", + "children": [ + { + "type": "label", + "label": "Collectors" + }, + { + "type": "dict", + "collapsable": true, + "key": "CollectMayaRender", + "label": "Collect Render Layers", + "children": [ + { + "type": "boolean", + "key": "sync_workfile_version", + "label": "Sync render version with workfile" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "label", + "label": "Collectors" + }, + { + "type": "dict", + "collapsable": true, + "key": "ValidateCameraAttributes", + "label": "Validate Camera Attributes", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "ValidateModelName", + "label": "Validate Model Name", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Path to material file defining list of material names to check. This is material name per line simple text file.
It will be checked against named group shader in your Validation regex.

For example:
^.*(?P=<shader>.+)_GEO

" + }, + { + "type": "path-widget", + "key": "material_file", + "label": "Material File", + "multiplatform": true, + "multipath": false + }, + { + "type": "text", + "key": "regex", + "label": "Validation regex" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "ValidateAssemblyName", + "label": "Validate Assembly Name", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "ValidateShaderName", + "label": "ValidateShaderName", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Shader name regex can use named capture group asset to validate against current asset name.

Example:
^.*(?P=<asset>.+)_SHD

" + }, + { + "type": "text", + "key": "regex", + "label": "Validation regex" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "ValidateMeshHasOverlappingUVs", + "label": "ValidateMeshHasOverlappingUVs", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "ValidateAttributes", + "label": "ValidateAttributes", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "raw-json", + "key": "attributes", + "label": "Attributes" + } + ] + }, + { + "type": "splitter" + }, + { + "type": "label", + "label": "Extractors" + }, + { + "type": "dict", + "collapsable": true, + "key": "ExtractCameraAlembic", + "label": "Extract camera to Alembic", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "List of attributes that will be added to the baked alembic camera. Needs to be written in python list syntax.

For example:
[\"attributeName\", \"anotherAttribute\"]

" + }, + { + "type": "boolean", + "key": "optional", + "label": "Optional" + }, + { + "type": "raw-json", + "key": "bake_attributes", + "label": "Bake Attributes" + } + ] + }, + { + "type": "dict", + "collapsable": true, + "key": "MayaSubmitDeadline", + "label": "Submit maya job to deadline", + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "enum", + "key": "tile_assembler_plugin", + "label": "Tile Assembler Plugin", + "multiselection": false, + "enum_items": [ + { + "DraftTileAssembler": "Draft Tile Assembler" + }, + { + "oiio": "Open Image IO" + } + ] + } + ] + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_publish_gui_filter.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_publish_gui_filter.json new file mode 100644 index 0000000000..efc6c1d629 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_publish_gui_filter.json @@ -0,0 +1,10 @@ +{ + "type": "dict-modifiable", + "collapsable": true, + "key": "filters", + "label": "Publish GUI Filters", + "object_type": { + "type": "raw-json", + "label": "Plugins" + } +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json new file mode 100644 index 0000000000..bf0aff2d41 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json @@ -0,0 +1,97 @@ +{ + "type": "dict", + "collapsable": true, + "key": "workfile_build", + "label": "Workfile Build Settings", + "children": [ + { + "type": "list", + "key": "profiles", + "label": "Profiles", + "object_type": { + "type": "dict", + "children": [ + { + "key": "tasks", + "label": "Tasks", + "type": "list", + "object_type": "text" + }, + { + "type": "splitter" + }, + { + "key": "current_context", + "label": "Current Context", + "type": "list", + "highlight_content": true, + "object_type": { + "type": "dict", + "children": [ + { + "key": "subset_name_filters", + "label": "Subset name Filters", + "type": "list", + "object_type": "text" + }, + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + }, + { + "key": "repre_names", + "label": "Repre Names", + "type": "list", + "object_type": "text" + }, + { + "key": "loaders", + "label": "Loaders", + "type": "list", + "object_type": "text" + } + ] + } + }, + { + "key": "linked_assets", + "label": "Linked Assets", + "type": "list", + "highlight_content": true, + "object_type": { + "type": "dict", + "children": [ + { + "key": "subset_name_filters", + "label": "Subset name Filters", + "type": "list", + "object_type": "text" + }, + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + }, + { + "key": "repre_names", + "label": "Repre Names", + "type": "list", + "object_type": "text" + }, + { + "key": "loaders", + "label": "Loaders", + "type": "list", + "object_type": "text" + } + ] + } + } + ] + } + } + ] +} diff --git a/pype/settings/entities/schemas/projects_schema/schemas/template_color.json b/pype/settings/entities/schemas/projects_schema/schemas/template_color.json new file mode 100644 index 0000000000..04ce055525 --- /dev/null +++ b/pype/settings/entities/schemas/projects_schema/schemas/template_color.json @@ -0,0 +1,30 @@ +[ + { + "type": "list-strict", + "key": "{name}", + "label": "{label}:", + "object_types": [ + { + "label": "Red", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + }, + { + "label": "Green", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + }, + { + "label": "Blue", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 3 + } + ] + } +] From 6c376fd9ff462d092e01e5d9a0953265469f317b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 15 Feb 2021 12:23:08 +0100 Subject: [PATCH 02/83] initial implementation of project settings entity --- pype/settings/entities/root_entities.py | 148 +++++++++++++++++++++++- 1 file changed, 145 insertions(+), 3 deletions(-) diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index 6e8ef1a9fb..1b5c7e4253 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -12,7 +12,11 @@ from .lib import ( OverrideState, gui_schema ) -from pype.settings.constants import SYSTEM_SETTINGS_KEY +from pype.settings.constants import ( + SYSTEM_SETTINGS_KEY, + PROJECT_SETTINGS_KEY, + PROJECT_ANATOMY_KEY +) from pype.settings.lib import ( DEFAULTS_DIR, @@ -20,9 +24,15 @@ from pype.settings.lib import ( get_default_settings, get_studio_system_settings_overrides, - save_studio_settings, + get_studio_project_settings_overrides, + get_studio_project_anatomy_overrides, + get_project_settings_overrides, + get_project_anatomy_overrides, + save_project_settings, + save_project_anatomy, + find_environments, apply_overrides ) @@ -478,7 +488,7 @@ class SystemSettings(RootEntity): Implementation of abstract method. """ - return os.path.join(DEFAULTS_DIR, SYSTEM_SETTINGS_KEY) + return DEFAULTS_DIR def _save_studio_values(self): settings_value = self.settings_value() @@ -521,3 +531,135 @@ class SystemSettings(RootEntity): overrides. """ raise ValueError("System settings can't save project overrides.") + + +class ProjectSettings(RootEntity): + """Root entity for project settings. + + Allows to modify project settings via entity system and loaded schemas. + + Args: + project_name (str): Project name which overrides will be loaded. + Use `None` to modify studio defaults. + change_state (bool): Set values on initialization. By + default is set to True. + reset (bool): Reset values on initialization. By default is set to + True. + schema_data (dict): Pass schema data to entity. This is for development + and debugging purposes. + """ + def __init__( + self, + project_name=None, + change_state=True, + reset=True, + schema_data=None + ): + self._project_name = project_name + + if schema_data is None: + # Load system schemas + schema_data = gui_schema("projects_schema", "schema_main") + + super(ProjectSettings, self).__init__(schema_data, reset) + + if change_state: + if self.project_name is None: + self.set_studio_state() + else: + self.set_project_state() + + @property + def project_name(self): + return self._project_name + + @project_name.setter + def project_name(self, project_name): + self.change_project(project_name) + + def change_project(self, project_name): + if project_name == self._project_name: + return + # TODO implement + self.log.warning("change_project not implemented yet!") + + def _reset_values(self): + + # PROJECT_SETTINGS_KEY, + # PROJECT_ANATOMY_KEY + # get_studio_project_settings_overrides, + # get_studio_project_anatomy_overrides, + # get_project_settings_overrides, + # get_project_anatomy_overrides, + # save_project_settings, + # save_project_anatomy, + + default_values = { + PROJECT_SETTINGS_KEY: get_default_settings()[PROJECT_SETTINGS_KEY], + PROJECT_ANATOMY_KEY: get_default_settings()[PROJECT_ANATOMY_KEY] + } + for key, child_obj in self.non_gui_children.items(): + value = default_values.get(key, NOT_SET) + child_obj.update_default_value(value) + + studio_overrides = { + PROJECT_SETTINGS_KEY: get_studio_project_settings_overrides(), + PROJECT_ANATOMY_KEY: get_studio_project_anatomy_overrides() + } + for key, child_obj in self.non_gui_children.items(): + value = studio_overrides.get(key, NOT_SET) + child_obj.update_studio_values(value) + + if not self.project_name: + return + + def reset(self, new_state=None): + """Discard changes and reset entit's values. + + Reload default values and studio override values and update entities. + + Args: + new_state (OverrideState): It is possible to change override state + during reset. Current state is used if not defined. + """ + if new_state is None: + new_state = self._override_state + + if new_state is OverrideState.NOT_DEFINED: + new_state = OverrideState.DEFAULTS + + if new_state is OverrideState.PROJECT: + raise ValueError("System settings can't store poject overrides.") + + self._reset_values() + self.set_override_state(new_state) + + def defaults_dir(self): + """Path to defaults directory. + + Implementation of abstract method. + """ + return os.path.join(DEFAULTS_DIR, SYSTEM_SETTINGS_KEY) + + def _save_studio_values(self): + settings_value = self.settings_value() + + self._validate_duplicated_env_group(settings_value) + + self.log.debug("Saving system settings: {}".format( + json.dumps(settings_value, indent=4) + )) + save_studio_settings(settings_value) + + def _validate_defaults_to_save(self, value): + """Valiations of default values before save.""" + pass + + def _save_project_values(self): + """System settings can't have project overrides. + + Raises: + ValueError: Raise when called as entity can't use or store project + overrides. + """ + self.log.warning("_save_project_values not implemented") From a166f21f94e6d429bf2c36d0812620abed40859f Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 15 Feb 2021 12:23:39 +0100 Subject: [PATCH 03/83] moved file_item attribute validation to InputEntity --- pype/settings/entities/input_entities.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pype/settings/entities/input_entities.py b/pype/settings/entities/input_entities.py index 700c883783..d64b697428 100644 --- a/pype/settings/entities/input_entities.py +++ b/pype/settings/entities/input_entities.py @@ -37,12 +37,6 @@ class EndpointEntity(ItemEntity): ) ) - # Input entity must have file parent. - if not self.file_item: - raise ValueError( - "{}: Missing parent file entity.".format(self.path) - ) - super(EndpointEntity, self).schema_validations() @abstractmethod @@ -100,6 +94,15 @@ class InputEntity(EndpointEntity): self.__class__.__name__ )) + def schema_validations(self): + # Input entity must have file parent. + if not self.file_item: + raise ValueError( + "{}: Missing parent file entity.".format(self.path) + ) + + super(EndpointEntity, self).schema_validations() + @property def value(self): """Entity's value without metadata.""" From 75cdac3e84f08cd2148039d10bd3c2a97a63cc85 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 15 Feb 2021 12:23:55 +0100 Subject: [PATCH 04/83] fixed "separator" type in GUIEntity --- pype/settings/entities/base_entity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/settings/entities/base_entity.py b/pype/settings/entities/base_entity.py index 763d67494c..4eef866b17 100644 --- a/pype/settings/entities/base_entity.py +++ b/pype/settings/entities/base_entity.py @@ -57,7 +57,7 @@ class GUIEntity(BaseEntity): """Entity without any specific logic that should be handled only in GUI.""" gui_type = True - schema_types = ["divider", "splitter", "label"] + schema_types = ["separator", "splitter", "label"] def __getitem__(self, key): return self.schema_data[key] From defbb567e58ac8f30eafe51a4627becfd1843d8e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 15 Feb 2021 12:24:13 +0100 Subject: [PATCH 05/83] removed checkbox_key in ftrack project settings --- .../entities/schemas/projects_schema/schema_project_ftrack.json | 1 - 1 file changed, 1 deletion(-) diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index 508b8e870d..0ba5abf29a 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -3,7 +3,6 @@ "key": "ftrack", "label": "Ftrack", "collapsable": true, - "checkbox_key": "enabled", "is_file": true, "children": [ { From bccc4337b5ec4f1ea14b506dec1be4eed059f3e4 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 15 Feb 2021 12:24:29 +0100 Subject: [PATCH 06/83] fix aces keys --- .../projects_schema/schemas/schema_anatomy_imageio.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json index 0032e3de06..d900818675 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json @@ -155,13 +155,13 @@ "spi-anim": "spi-anim" }, { - "aces_1.0.3": "aces_0.1.1" + "aces_0.1.1": "aces_0.1.1" }, { - "aces_1.0.3": "aces_0.7.1" + "aces_0.7.1": "aces_0.7.1" }, { - "aces_1.0.3": "aces_1.0.1" + "aces_1.0.1": "aces_1.0.1" }, { "aces_1.0.3": "aces_1.0.3" From a19db9a521dc5d18bbef86a31dbd6906d3b3bf94 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 15 Feb 2021 18:12:16 +0100 Subject: [PATCH 07/83] anatomy entities and ProjectSettings --- pype/settings/entities/__init__.py | 16 ++++++++++++++-- pype/settings/entities/anatomy_entities.py | 10 ++++++++++ .../schemas/projects_schema/schema_main.json | 9 +++++++-- 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 pype/settings/entities/anatomy_entities.py diff --git a/pype/settings/entities/__init__.py b/pype/settings/entities/__init__.py index 2c53416cbd..fbc08ca51d 100644 --- a/pype/settings/entities/__init__.py +++ b/pype/settings/entities/__init__.py @@ -73,7 +73,10 @@ from .base_entity import ( ItemEntity ) -from .root_entities import SystemSettings +from .root_entities import ( + SystemSettings, + ProjectSettings +) from .item_entities import ( PathEntity, @@ -96,6 +99,11 @@ from .list_entity import ListEntity from .dict_immutable_keys_entity import DictImmutableKeysEntity from .dict_mutable_keys_entity import DictMutableKeysEntity +from .anatomy_entities import ( + AnatomyEntity, + AnatomyRootsEntity +) + __all__ = ( "DefaultsNotDefined", @@ -115,6 +123,7 @@ __all__ = ( "ItemEntity", "SystemSettings", + "ProjectSettings", "PathEntity", "ListStrictEntity", @@ -133,5 +142,8 @@ __all__ = ( "DictImmutableKeysEntity", - "DictMutableKeysEntity" + "DictMutableKeysEntity", + + "AnatomyEntity", + "AnatomyRootsEntity" ) diff --git a/pype/settings/entities/anatomy_entities.py b/pype/settings/entities/anatomy_entities.py new file mode 100644 index 0000000000..f89318e213 --- /dev/null +++ b/pype/settings/entities/anatomy_entities.py @@ -0,0 +1,10 @@ +from .dict_immutable_keys_entity import DictImmutableKeysEntity +from .dict_mutable_keys_entity import DictMutableKeysEntity + + +class AnatomyEntity(DictImmutableKeysEntity): + schema_types = ["anatomy"] + + +class AnatomyRootsEntity(DictMutableKeysEntity): + schema_types = ["anatomy_roots"] diff --git a/pype/settings/entities/schemas/projects_schema/schema_main.json b/pype/settings/entities/schemas/projects_schema/schema_main.json index 73266a9e79..51371b8cfd 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_main.json +++ b/pype/settings/entities/schemas/projects_schema/schema_main.json @@ -7,10 +7,15 @@ "key": "project_anatomy", "children": [ { - "type": "anatomy_roots", "key": "roots", "label": "Roots", - "is_file": true + "type": "anatomy_roots", + "is_file": true, + "expandable": false, + "object_type": { + "type": "path-widget", + "multiplatform": true + } }, { "type": "schema", From 5fea4a3cbb9e7a15391224a38eb2db4d30f44b9e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 15 Feb 2021 18:27:06 +0100 Subject: [PATCH 08/83] added schema readme --- pype/settings/__init__.py | 8 +- pype/settings/entities/schemas/README.md | 490 +++++++++++++++++++++++ 2 files changed, 496 insertions(+), 2 deletions(-) create mode 100644 pype/settings/entities/schemas/README.md diff --git a/pype/settings/__init__.py b/pype/settings/__init__.py index 56f342558e..b4187829fc 100644 --- a/pype/settings/__init__.py +++ b/pype/settings/__init__.py @@ -5,7 +5,10 @@ from .lib import ( get_anatomy_settings, get_environments ) -from .entities import SystemSettings +from .entities import ( + SystemSettings, + ProjectSettings +) __all__ = ( @@ -15,5 +18,6 @@ __all__ = ( "get_anatomy_settings", "get_environments", - "SystemSettings" + "SystemSettings", + "ProjectSettings" ) diff --git a/pype/settings/entities/schemas/README.md b/pype/settings/entities/schemas/README.md new file mode 100644 index 0000000000..643043b6c8 --- /dev/null +++ b/pype/settings/entities/schemas/README.md @@ -0,0 +1,490 @@ +# Creating GUI schemas + +## Basic rules +- configurations does not define GUI, but GUI defines configurations! +- output is always json (yaml is not needed for anatomy templates anymore) +- GUI schema has multiple input types, all inputs are represented by a dictionary +- each input may have "input modifiers" (keys in dictionary) that are required or optional + - only required modifier for all input items is key `"type"` which says what type of item it is +- there are special keys across all inputs + - `"is_file"` - this key is for storing pype defaults in `pype` repo + - reasons of existence: developing new schemas does not require to create defaults manually + - key is validated, must be once in hierarchy else it won't be possible to store pype defaults + - `"is_group"` - define that all values under key in hierarchy will be overriden if any value is modified, this information is also stored to overrides + - this keys is not allowed for all inputs as they may have not reason for that + - key is validated, can be only once in hierarchy but is not required +- currently there are `system configurations` and `project configurations` + +## Inner schema +- GUI schemas are huge json files, to be able to split whole configuration into multiple schema there's type `schema` +- system configuration schemas are stored in `~/tools/settings/settings/gui_schemas/system_schema/` and project configurations in `~/tools/settings/settings/gui_schemas/projects_schema/` +- each schema name is filename of json file except extension (without ".json") +- if content is dictionary content will be used as `schema` else will be used as `schema_template` + +### schema +- can have only key `"children"` which is list of strings, each string should represent another schema (order matters) string represebts name of the schema +- will just paste schemas from other schema file in order of "children" list + +``` +{ + "type": "schema", + "name": "my_schema_name" +} +``` + +### schema_template +- allows to define schema "templates" to not duplicate same content multiple times +```javascript +// EXAMPLE json file content (filename: example_template.json) +[ + { + "__default_values__": { + "multipath_executables": true + } + }, { + "type": "raw-json", + "label": "{host_label} Environments", + "key": "{host_name}_environments", + "env_group_key": "{host_name}" + }, { + "type": "path-widget", + "key": "{host_name}_executables", + "label": "{host_label} - Full paths to executables", + "multiplatform": "{multipath_executables}", + "multipath": true + } +] +``` +```javascript +// EXAMPLE usage of the template in schema +{ + "type": "dict", + "key": "schema_template_examples", + "label": "Schema template examples", + "children": [ + { + "type": "schema_template", + // filename of template (example_template.json) + "name": "example_template", + "template_data": { + "host_label": "Maya 2019", + "host_name": "maya_2019", + "multipath_executables": false + } + }, { + "type": "schema_template", + "name": "example_template", + "template_data": { + "host_label": "Maya 2020", + "host_name": "maya_2020" + } + } + ] +} +``` +- item in schema mush contain `"type"` and `"name"` keys but it is also expected that `"template_data"` will be entered too +- all items in the list, except `__default_values__`, will replace `schema_template` item in schema +- template may contain another template or schema +- it is expected that schema template will have unfilled fields as in example + - unfilled fields are allowed only in values of schema dictionary +```javascript +{ + ... + // Allowed + "key": "{to_fill}" + ... + // Not allowed + "{to_fill}": "value" + ... +} +``` +- Unfilled fields can be also used for non string values, in that case value must contain only one key and value for fill must contain right type. +```javascript +{ + ... + // Allowed + "multiplatform": "{executable_multiplatform}" + ... + // Not allowed + "multiplatform": "{executable_multiplatform}_enhanced_string" + ... +} +``` +- It is possible to define default values for unfilled fields to do so one of items in list must be dictionary with key `"__default_values__"` and value as dictionary with default key: values (as in example above). + + +## Basic Dictionary inputs +- these inputs wraps another inputs into {key: value} relation + +## dict +- this is another dictionary input wrapping more inputs but visually makes them different +- item may be used as widget (in `list` or `dict-modifiable`) + - in that case the only key modifier is `children` which is list of it's keys + - USAGE: e.g. List of dictionaries where each dictionary have same structure. +- item may be with or without `"label"` if is not used as widget + - required keys are `"key"` under which will be stored + - without label it is just wrap item holding `"key"` + - can't have `"is_group"` key set to True as it breaks visual override showing + - if `"label"` is entetered there which will be shown in GUI + - item with label can be collapsable + - that can be set with key `"collapsable"` as `True`/`False` (Default: `True`) + - with key `"collapsed"` as `True`/`False` can be set that is collapsed when GUI is opened (Default: `False`) + - it is possible to add darker background with `"highlight_content"` (Default: `False`) + - darker background has limits of maximum applies after 3-4 nested highlighted items there is not difference in the color + - output is dictionary `{the "key": children values}` +``` +# Example +{ + "key": "applications", + "type": "dict", + "label": "Applications", + "collapsable": true, + "highlight_content": true, + "is_group": true, + "is_file": true, + "children": [ + ...ITEMS... + ] +} + +# Without label +{ + "type": "dict", + "key": "global", + "children": [ + ...ITEMS... + ] +} + +# When used as widget +{ + "type": "list", + "key": "profiles", + "label": "Profiles", + "object_type": { + "type": "dict", + "children": [ + { + "key": "families", + "label": "Families", + "type": "list", + "object_type": "text" + }, { + "key": "hosts", + "label": "Hosts", + "type": "list", + "object_type": "text" + } + ... + ] + } +} +``` + +## Inputs for setting any kind of value (`Pure` inputs) +- all these input must have defined `"key"` under which will be stored and `"label"` which will be shown next to input + - unless they are used in different types of inputs (later) "as widgets" in that case `"key"` and `"label"` are not required as there is not place where to set them + +### boolean +- simple checkbox, nothing more to set +``` +{ + "type": "boolean", + "key": "my_boolean_key", + "label": "Do you want to use Pype?" +} +``` + +### number +- number input, can be used for both integer and float + - key `"decimal"` defines how many decimal places will be used, 0 is for integer input (Default: `0`) + - key `"minimum"` as minimum allowed number to enter (Default: `-99999`) + - key `"maxium"` as maximum allowed number to enter (Default: `99999`) +``` +{ + "type": "number", + "key": "fps", + "label": "Frame rate (FPS)" + "decimal": 2, + "minimum": 1, + "maximum": 300000 +} +``` + +### text +- simple text input + - key `"multiline"` allows to enter multiple lines of text (Default: `False`) + - key `"placeholder"` allows to show text inside input when is empty (Default: `None`) + +``` +{ + "type": "text", + "key": "deadline_pool", + "label": "Deadline pool" +} +``` + +### path-input +- enhanced text input + - does not allow to enter backslash, is auto-converted to forward slash + - may be added another validations, like do not allow end path with slash +- this input is implemented to add additional features to text input +- this is meant to be used in proxy input `path-widget` + - DO NOT USE this input in schema please + +### raw-json +- a little bit enhanced text input for raw json +- has validations of json format + - empty value is invalid value, always must be at least `{}` of `[]` + +``` +{ + "type": "raw-json", + "key": "profiles", + "label": "Extract Review profiles" +} +``` + +### enum +- returns value of single on multiple items from predefined values +- multiselection can be allowed with setting key `"multiselection"` to `True` (Default: `False`) +- values are defined under value of key `"enum_items"` as list + - each item in list is simple dictionary where value is label and key is value which will be stored + - should be possible to enter single dictionary if order of items doesn't matter + +``` +{ + "key": "tags", + "label": "Tags", + "type": "enum", + "multiselection": true, + "enum_items": [ + {"burnin": "Add burnins"}, + {"ftrackreview": "Add to Ftrack"}, + {"delete": "Delete output"}, + {"slate-frame": "Add slate frame"}, + {"no-hnadles": "Skip handle frames"} + ] +} +``` + +## Inputs for setting value using Pure inputs +- these inputs also have required `"key"` +- attribute `"label"` is required in few conditions + - when item is marked `as_group` or when `use_label_wrap` +- they use Pure inputs "as widgets" + +### list +- output is list +- items can be added and removed +- items in list must be the same type +- to wrap item in collapsible widget with label on top set `use_label_wrap` to `True` + - when this is used `collapsible` and `collapsed` can be set (same as `dict` item does) +- type of items is defined with key `"object_type"` +- there are 2 possible ways how to set the type: + 1.) dictionary with item modifiers (`number` input has `minimum`, `maximum` and `decimals`) in that case item type must be set as value of `"type"` (example below) + 2.) item type name as string without modifiers (e.g. `text`) + +1.) with item modifiers +``` +{ + "type": "list", + "key": "exclude_ports", + "label": "Exclude ports", + "object_type": { + "type": "number", # number item type + "minimum": 1, # minimum modifier + "maximum": 65535 # maximum modifier + } +} +``` + +2.) without modifiers +``` +{ + "type": "list", + "key": "exclude_ports", + "label": "Exclude ports", + "object_type": "text" +} +``` + +### dict-modifiable +- one of dictionary inputs, this is only used as value input +- items in this input can be removed and added same way as in `list` input +- value items in dictionary must be the same type +- type of items is defined with key `"object_type"` +- required keys may be defined under `"required_keys"` + - required keys must be defined as a list (e.g. `["key_1"]`) and are moved to the top + - these keys can't be removed or edited (it is possible to edit label if item is collapsible) +- there are 2 possible ways how to set the type: + 1.) dictionary with item modifiers (`number` input has `minimum`, `maximum` and `decimals`) in that case item type must be set as value of `"type"` (example below) + 2.) item type name as string without modifiers (e.g. `text`) +- this input can be collapsable + - that can be set with key `"collapsable"` as `True`/`False` (Default: `True`) + - with key `"collapsed"` as `True`/`False` can be set that is collapsed when GUI is opened (Default: `False`) + +1.) with item modifiers +``` +{ + "type": "dict-modifiable", + "object_type": { + "type": "number", + "minimum": 0, + "maximum": 300 + }, + "is_group": true, + "key": "templates_mapping", + "label": "Muster - Templates mapping", + "is_file": true +} +``` + +2.) without modifiers +``` +{ + "type": "dict-modifiable", + "object_type": "text", + "is_group": true, + "key": "templates_mapping", + "label": "Muster - Templates mapping", + "is_file": true +} +``` + +### path-widget +- input for paths, use `path-input` internally +- has 2 input modifiers `"multiplatform"` and `"multipath"` + - `"multiplatform"` - adds `"windows"`, `"linux"` and `"darwin"` path inputs result is dictionary + - `"multipath"` - it is possible to enter multiple paths + - if both are enabled result is dictionary with lists + +``` +{ + "type": "path-widget", + "key": "ffmpeg_path", + "label": "FFmpeg path", + "multiplatform": true, + "multipath": true +} +``` + +### list-strict +- input for strict number of items in list +- each child item can be different type with different possible modifiers +- it is possible to display them in horizontal or vertical layout + - key `"horizontal"` as `True`/`False` (Default: `True`) +- each child may have defined `"label"` which is shown next to input + - label does not reflect modifications or overrides (TODO) +- children item are defined under key `"object_types"` which is list of dictionaries + - key `"children"` is not used because is used for hierarchy validations in schema +- USAGE: For colors, transformations, etc. Custom number and different modifiers + give ability to define if color is HUE or RGB, 0-255, 0-1, 0-100 etc. + +``` +{ + "type": "list-strict", + "key": "color", + "label": "Color", + "object_types": [ + { + "label": "Red", + "type": "number", + "minimum": 0, + "maximum": 255, + "decimal": 0 + }, { + "label": "Green", + "type": "number", + "minimum": 0, + "maximum": 255, + "decimal": 0 + }, { + "label": "Blue", + "type": "number", + "minimum": 0, + "maximum": 255, + "decimal": 0 + }, { + "label": "Alpha", + "type": "number", + "minimum": 0, + "maximum": 1, + "decimal": 6 + } + ] +} +``` + + +## Noninteractive widgets +- have nothing to do with data + +### label +- add label with note or explanations +- it is possible to use html tags inside the label + +``` +{ + "type": "label", + "label": "RED LABEL: Normal label" +} +``` + +### splitter +- visual splitter of items (more divider than splitter) + +``` +{ + "type": "splitter" +} +``` + +## Proxy wrappers +- should wraps multiple inputs only visually +- these does not have `"key"` key and do not allow to have `"is_file"` or `"is_group"` modifiers enabled +- can't be used as widget (first item in e.g. `list`, `dict-modifiable`, etc.) + +### form +- wraps inputs into form look layout +- should be used only for Pure inputs + +``` +{ + "type": "dict-form", + "children": [ + { + "type": "text", + "key": "deadline_department", + "label": "Deadline apartment" + }, { + "type": "number", + "key": "deadline_priority", + "label": "Deadline priority" + }, { + ... + } + ] +} +``` + + +### collapsible-wrap +- wraps inputs into collapsible widget + - looks like `dict` but does not hold `"key"` +- should be used only for Pure inputs + +``` +{ + "type": "collapsible-wrap", + "label": "Collapsible example" + "children": [ + { + "type": "text", + "key": "_example_input_collapsible", + "label": "Example input in collapsible wrapper" + }, { + ... + } + ] +} From 8e5f2f0f017556165f96b785b7974697ca1135ac Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 12:53:22 +0100 Subject: [PATCH 09/83] added is_group to imageio settings --- .../schemas/projects_schema/schemas/schema_anatomy_imageio.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json index d900818675..2c8b1b213a 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json @@ -88,6 +88,7 @@ "type": "dict", "label": "Colorspace on Inputs by regex detection", "collapsable": true, + "is_group": true, "children": [ { "type": "list", @@ -324,6 +325,7 @@ "key": "regexInputs", "type": "dict", "label": "Colorspace on Inputs by regex detection", + "is_group": true, "collapsable": true, "children": [ { From 709053fbde0b55fd5990f9d93d10b795b5c8ea66 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 12:53:52 +0100 Subject: [PATCH 10/83] added groups to ftrack events/actions settings --- .../schemas/projects_schema/schema_project_ftrack.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index 0ba5abf29a..d27e99da8a 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -161,6 +161,7 @@ "type": "dict", "key": "status_update", "label": "Update status on task action", + "is_group": true, "checkbox_key": "enabled", "children": [ { @@ -239,6 +240,7 @@ "type": "dict", "key": "status_task_to_version", "label": "Sync status from Task to Version", + "is_group": true, "checkbox_key": "enabled", "children": [ { @@ -271,6 +273,7 @@ "type": "dict", "key": "status_version_to_task", "label": "Sync status from Version to Task", + "is_group": true, "checkbox_key": "enabled", "children": [ { @@ -326,6 +329,7 @@ { "type": "dict", "key": "next_task_update", + "is_group": true, "label": "Update status on next task", "checkbox_key": "enabled", "children": [ @@ -385,6 +389,7 @@ { "type": "dict", "key": "application_launch_statuses", + "is_group": true, "label": "Application - Status change on launch", "checkbox_key": "enabled", "children": [ From 0ca7ace1f3380b6ce462da1a0c56dc4fcee936e3 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 13:01:18 +0100 Subject: [PATCH 11/83] moved ProjectListWidget to widgets.py --- .../settings/settings/widgets/__init__.py | 2 +- .../settings/settings/widgets/categories.py | 157 +----------------- .../settings/settings/widgets/widgets.py | 154 +++++++++++++++++ 3 files changed, 160 insertions(+), 153 deletions(-) diff --git a/pype/tools/settings/settings/widgets/__init__.py b/pype/tools/settings/settings/widgets/__init__.py index 03cc3224da..653e0d0ac8 100644 --- a/pype/tools/settings/settings/widgets/__init__.py +++ b/pype/tools/settings/settings/widgets/__init__.py @@ -1,5 +1,5 @@ from .window import MainWidget -from .categories import ProjectListWidget +from .widgets import ProjectListWidget from . import item_types from . import anatomy_types diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index b26438ee4f..2bbeb08a72 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -43,7 +43,10 @@ from pype.settings.lib import ( get_system_settings ) -from .widgets import UnsavedChangesDialog +from .widgets import ( + UnsavedChangesDialog, + ProjectListWidget +) from . import lib from .base import GUIWidget @@ -59,10 +62,7 @@ from .item_widgets import ( PathWidget, PathInputWidget ) -from avalon.mongodb import ( - AvalonMongoConnection, - AvalonMongoDB -) + from avalon.vendor import qtawesome @@ -658,153 +658,6 @@ class SystemWidget(SettingsCategoryWidget): ) -class ProjectListView(QtWidgets.QListView): - left_mouse_released_at = QtCore.Signal(QtCore.QModelIndex) - - def mouseReleaseEvent(self, event): - if event.button() == QtCore.Qt.LeftButton: - index = self.indexAt(event.pos()) - self.left_mouse_released_at.emit(index) - super(ProjectListView, self).mouseReleaseEvent(event) - - -class ProjectListWidget(QtWidgets.QWidget): - default = "< Default >" - project_changed = QtCore.Signal() - - def __init__(self, parent): - self._parent = parent - - self.current_project = None - - super(ProjectListWidget, self).__init__(parent) - self.setObjectName("ProjectListWidget") - - label_widget = QtWidgets.QLabel("Projects") - project_list = ProjectListView(self) - project_list.setModel(QtGui.QStandardItemModel()) - - # Do not allow editing - project_list.setEditTriggers( - QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers - ) - # Do not automatically handle selection - project_list.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) - - layout = QtWidgets.QVBoxLayout(self) - layout.setSpacing(3) - layout.addWidget(label_widget, 0) - layout.addWidget(project_list, 1) - - project_list.left_mouse_released_at.connect(self.on_item_clicked) - - self.project_list = project_list - - self.dbcon = None - - def on_item_clicked(self, new_index): - new_project_name = new_index.data(QtCore.Qt.DisplayRole) - if new_project_name is None: - return - - if self.current_project == new_project_name: - return - - save_changes = False - change_project = False - if self.validate_context_change(): - change_project = True - - else: - dialog = UnsavedChangesDialog(self) - result = dialog.exec_() - if result == 1: - save_changes = True - change_project = True - - elif result == 2: - change_project = True - - if save_changes: - self._parent._save() - - if change_project: - self.select_project(new_project_name) - self.current_project = new_project_name - self.project_changed.emit() - else: - self.select_project(self.current_project) - - def validate_context_change(self): - # TODO add check if project can be changed (is modified) - for item in self._parent.input_fields: - is_modified = item.child_modified - if is_modified: - return False - return True - - def project_name(self): - if self.current_project == self.default: - return None - return self.current_project - - def select_project(self, project_name): - model = self.project_list.model() - found_items = model.findItems(project_name) - if not found_items: - found_items = model.findItems(self.default) - - index = model.indexFromItem(found_items[0]) - self.project_list.selectionModel().clear() - self.project_list.selectionModel().setCurrentIndex( - index, QtCore.QItemSelectionModel.SelectionFlag.SelectCurrent - ) - - def refresh(self): - selected_project = None - for index in self.project_list.selectedIndexes(): - selected_project = index.data(QtCore.Qt.DisplayRole) - break - - model = self.project_list.model() - model.clear() - - items = [self.default] - - system_settings = get_system_settings() - mongo_url = system_settings["modules"]["avalon"]["AVALON_MONGO"] - if not mongo_url: - mongo_url = os.environ["PYPE_MONGO"] - - # Force uninstall of whole avalon connection if url does not match - # to current environment and set it as environment - if mongo_url != os.environ["AVALON_MONGO"]: - AvalonMongoConnection.uninstall(self.dbcon, force=True) - os.environ["AVALON_MONGO"] = mongo_url - self.dbcon = None - - if not self.dbcon: - try: - self.dbcon = AvalonMongoDB() - self.dbcon.install() - except Exception: - self.dbcon = None - self.current_project = None - - if self.dbcon: - for project_doc in tuple(self.dbcon.projects()): - items.append(project_doc["name"]) - - for item in items: - model.appendRow(QtGui.QStandardItem(item)) - - self.select_project(selected_project) - - self.current_project = self.project_list.currentIndex().data( - QtCore.Qt.DisplayRole - ) - - class ProjectWidget(SettingsCategoryWidget): schema_category = "projects_schema" initial_schema_name = "schema_main" diff --git a/pype/tools/settings/settings/widgets/widgets.py b/pype/tools/settings/settings/widgets/widgets.py index 3a7cbfddf9..9c0e58d52a 100644 --- a/pype/tools/settings/settings/widgets/widgets.py +++ b/pype/tools/settings/settings/widgets/widgets.py @@ -1,5 +1,12 @@ +import os from Qt import QtWidgets, QtCore, QtGui from avalon.vendor import qtawesome +from avalon.mongodb import ( + AvalonMongoConnection, + AvalonMongoDB +) + +from pype.settings.lib import get_system_settings class ShadowWidget(QtWidgets.QWidget): @@ -523,3 +530,150 @@ class NiceCheckbox(QtWidgets.QFrame): event.accept() return return super(NiceCheckbox, self).mouseReleaseEvent(event) + + +class ProjectListView(QtWidgets.QListView): + left_mouse_released_at = QtCore.Signal(QtCore.QModelIndex) + + def mouseReleaseEvent(self, event): + if event.button() == QtCore.Qt.LeftButton: + index = self.indexAt(event.pos()) + self.left_mouse_released_at.emit(index) + super(ProjectListView, self).mouseReleaseEvent(event) + + +class ProjectListWidget(QtWidgets.QWidget): + default = "< Default >" + project_changed = QtCore.Signal() + + def __init__(self, parent): + self._parent = parent + + self.current_project = None + + super(ProjectListWidget, self).__init__(parent) + self.setObjectName("ProjectListWidget") + + label_widget = QtWidgets.QLabel("Projects") + project_list = ProjectListView(self) + project_list.setModel(QtGui.QStandardItemModel()) + + # Do not allow editing + project_list.setEditTriggers( + QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers + ) + # Do not automatically handle selection + project_list.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) + + layout = QtWidgets.QVBoxLayout(self) + layout.setSpacing(3) + layout.addWidget(label_widget, 0) + layout.addWidget(project_list, 1) + + project_list.left_mouse_released_at.connect(self.on_item_clicked) + + self.project_list = project_list + + self.dbcon = None + + def on_item_clicked(self, new_index): + new_project_name = new_index.data(QtCore.Qt.DisplayRole) + if new_project_name is None: + return + + if self.current_project == new_project_name: + return + + save_changes = False + change_project = False + if self.validate_context_change(): + change_project = True + + else: + dialog = UnsavedChangesDialog(self) + result = dialog.exec_() + if result == 1: + save_changes = True + change_project = True + + elif result == 2: + change_project = True + + if save_changes: + self._parent._save() + + if change_project: + self.select_project(new_project_name) + self.current_project = new_project_name + self.project_changed.emit() + else: + self.select_project(self.current_project) + + def validate_context_change(self): + # TODO add check if project can be changed (is modified) + for item in self._parent.input_fields: + is_modified = item.child_modified + if is_modified: + return False + return True + + def project_name(self): + if self.current_project == self.default: + return None + return self.current_project + + def select_project(self, project_name): + model = self.project_list.model() + found_items = model.findItems(project_name) + if not found_items: + found_items = model.findItems(self.default) + + index = model.indexFromItem(found_items[0]) + self.project_list.selectionModel().clear() + self.project_list.selectionModel().setCurrentIndex( + index, QtCore.QItemSelectionModel.SelectionFlag.SelectCurrent + ) + + def refresh(self): + selected_project = None + for index in self.project_list.selectedIndexes(): + selected_project = index.data(QtCore.Qt.DisplayRole) + break + + model = self.project_list.model() + model.clear() + + items = [self.default] + + system_settings = get_system_settings() + mongo_url = system_settings["modules"]["avalon"]["AVALON_MONGO"] + if not mongo_url: + mongo_url = os.environ["PYPE_MONGO"] + + # Force uninstall of whole avalon connection if url does not match + # to current environment and set it as environment + if mongo_url != os.environ["AVALON_MONGO"]: + AvalonMongoConnection.uninstall(self.dbcon, force=True) + os.environ["AVALON_MONGO"] = mongo_url + self.dbcon = None + + if not self.dbcon: + try: + self.dbcon = AvalonMongoDB() + self.dbcon.install() + except Exception: + self.dbcon = None + self.current_project = None + + if self.dbcon: + for project_doc in tuple(self.dbcon.projects()): + items.append(project_doc["name"]) + + for item in items: + model.appendRow(QtGui.QStandardItem(item)) + + self.select_project(selected_project) + + self.current_project = self.project_list.currentIndex().data( + QtCore.Qt.DisplayRole + ) From 0042c6f875835d89f662e96411288fd20cbf66fc Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 14:10:48 +0100 Subject: [PATCH 12/83] modified project's category widget to use entity --- .../settings/settings/widgets/categories.py | 668 +++++------------- 1 file changed, 182 insertions(+), 486 deletions(-) diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index 2bbeb08a72..d2e3ce0d1a 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -8,6 +8,7 @@ from pype.settings.constants import ( ) from pype.settings.entities import ( SystemSettings, + ProjectSettings, GUIEntity, DictImmutableKeysEntity, @@ -27,20 +28,9 @@ from pype.settings.entities import ( ) from pype.settings.lib import ( - DEFAULTS_DIR, - reset_default_settings, get_default_settings, - get_studio_project_settings_overrides, - get_studio_project_anatomy_overrides, - - get_project_settings_overrides, - get_project_anatomy_overrides, - - save_project_settings, - save_project_anatomy, - get_system_settings ) from .widgets import ( @@ -71,10 +61,23 @@ class CategoryState(Enum): Working = object() -class SettingsCategoryWidget(QtWidgets.QWidget): - schema_category = None - initial_schema_name = None +class IgnoreInputChangesObj: + def __init__(self, top_widget): + self._ignore_changes = False + self.top_widget = top_widget + def __bool__(self): + return self._ignore_changes + + def set_ignore(self, ignore_changes=True): + if self._ignore_changes == ignore_changes: + return + self._ignore_changes = ignore_changes + if not ignore_changes: + self.top_widget.hierarchical_style_update() + + +class SettingsCategoryWidget(QtWidgets.QWidget): state_changed = QtCore.Signal() saved = QtCore.Signal(QtWidgets.QWidget) @@ -83,9 +86,18 @@ class SettingsCategoryWidget(QtWidgets.QWidget): self.user_role = user_role + self.entity = None + self._state = CategoryState.Idle + self._hide_studio_overrides = False + self.ignore_input_changes = IgnoreInputChangesObj(self) + + self.keys = [] + self.input_fields = [] + self.initialize_attributes() + self.create_ui() @staticmethod @@ -152,357 +164,8 @@ class SettingsCategoryWidget(QtWidgets.QWidget): app.processEvents() def initialize_attributes(self): - self._hide_studio_overrides = False - self._ignore_value_changes = False - - self.keys = [] - self.input_fields = [] - self.schema = None - self.main_schema_key = None - - # Required attributes for items - self.is_overidable = False - self._has_studio_override = False - self._is_overriden = False - self._as_widget = False - self._is_group = False - self._any_parent_as_widget = False - self._any_parent_is_group = False - self.has_studio_override = self._has_studio_override - self.is_overriden = self._is_overriden - self.as_widget = self._as_widget - self.is_group = self._as_widget - self.any_parent_as_widget = self._any_parent_as_widget - self.any_parent_is_group = self._any_parent_is_group - - def create_ui(self): - scroll_widget = QtWidgets.QScrollArea(self) - scroll_widget.setObjectName("GroupWidget") - content_widget = QtWidgets.QWidget(scroll_widget) - content_layout = QtWidgets.QVBoxLayout(content_widget) - content_layout.setContentsMargins(3, 3, 3, 3) - content_layout.setSpacing(0) - content_layout.setAlignment(QtCore.Qt.AlignTop) - - scroll_widget.setWidgetResizable(True) - scroll_widget.setWidget(content_widget) - - configurations_widget = QtWidgets.QWidget(self) - - footer_widget = QtWidgets.QWidget(configurations_widget) - footer_layout = QtWidgets.QHBoxLayout(footer_widget) - - if self.user_role == "developer": - self._add_developer_ui(footer_layout) - - save_btn = QtWidgets.QPushButton("Save") - spacer_widget = QtWidgets.QWidget() - footer_layout.addWidget(spacer_widget, 1) - footer_layout.addWidget(save_btn, 0) - - configurations_layout = QtWidgets.QVBoxLayout(configurations_widget) - configurations_layout.setContentsMargins(0, 0, 0, 0) - configurations_layout.setSpacing(0) - - configurations_layout.addWidget(scroll_widget, 1) - configurations_layout.addWidget(footer_widget, 0) - - main_layout = QtWidgets.QHBoxLayout(self) - main_layout.setContentsMargins(0, 0, 0, 0) - main_layout.setSpacing(0) - main_layout.addWidget(configurations_widget, 1) - - save_btn.clicked.connect(self._save) - - self.scroll_widget = scroll_widget - self.content_layout = content_layout - self.content_widget = content_widget - self.configurations_widget = configurations_widget - self.main_layout = main_layout - - self.ui_tweaks() - - def ui_tweaks(self): return - def _add_developer_ui(self, footer_layout): - save_as_default_btn = QtWidgets.QPushButton("Save as Default") - - refresh_icon = qtawesome.icon("fa.refresh", color="white") - refresh_button = QtWidgets.QPushButton() - refresh_button.setIcon(refresh_icon) - - hide_studio_overrides = QtWidgets.QCheckBox() - hide_studio_overrides.setChecked(self._hide_studio_overrides) - - hide_studio_overrides_widget = QtWidgets.QWidget() - hide_studio_overrides_layout = QtWidgets.QHBoxLayout( - hide_studio_overrides_widget - ) - _label_widget = QtWidgets.QLabel( - "Hide studio overrides", hide_studio_overrides_widget - ) - hide_studio_overrides_layout.addWidget(_label_widget) - hide_studio_overrides_layout.addWidget(hide_studio_overrides) - - footer_layout.addWidget(save_as_default_btn, 0) - footer_layout.addWidget(refresh_button, 0) - footer_layout.addWidget(hide_studio_overrides_widget, 0) - - save_as_default_btn.clicked.connect(self._save_as_defaults) - refresh_button.clicked.connect(self._on_refresh) - hide_studio_overrides.stateChanged.connect( - self._on_hide_studio_overrides - ) - - def save(self): - """Save procedure.""" - raise NotImplementedError("Method `save` is not implemented.") - - def defaults_dir(self): - """Path to defaults folder.""" - raise NotImplementedError("Method `defaults_dir` is not implemented.") - - def update_values(self): - """Procedure of update values of items on context change or reset.""" - raise NotImplementedError("Method `update_values` is not implemented.") - - def validate_defaults_to_save(self, value): - raise NotImplementedError( - "Method `validate_defaults_to_save` not implemented." - ) - - def any_parent_overriden(self): - return False - - @property - def ignore_value_changes(self): - return self._ignore_value_changes - - @ignore_value_changes.setter - def ignore_value_changes(self, value): - self._ignore_value_changes = value - if value is False: - self.hierarchical_style_update() - - def hierarchical_style_update(self): - for input_field in self.input_fields: - input_field.hierarchical_style_update() - - def reset(self): - self.set_state(CategoryState.Working) - - reset_default_settings() - - self.keys.clear() - self.input_fields.clear() - while self.content_layout.count() != 0: - widget = self.content_layout.itemAt(0).widget() - widget.setVisible(False) - self.content_layout.removeWidget(widget) - widget.deleteLater() - - self.schema = lib.gui_schema( - self.schema_category, self.initial_schema_name - ) - - self.main_schema_key = self.schema["key"] - - self.add_children_gui(self.schema) - self._update_values() - - self.hierarchical_style_update() - - self.set_state(CategoryState.Idle) - - def items_are_valid(self): - has_invalid = False - for item in self.input_fields: - if item.child_invalid: - has_invalid = True - - if not has_invalid: - return True - - invalid_items = [] - for item in self.input_fields: - invalid_items.extend(item.get_invalid()) - msg_box = QtWidgets.QMessageBox( - QtWidgets.QMessageBox.Warning, - "Invalid input", - "There is invalid value in one of inputs." - " Please lead red color and fix them." - ) - msg_box.setStandardButtons(QtWidgets.QMessageBox.Ok) - msg_box.exec_() - - first_invalid_item = invalid_items[0] - self.scroll_widget.ensureWidgetVisible(first_invalid_item) - if first_invalid_item.isVisible(): - first_invalid_item.setFocus(True) - return False - - def on_saved(self, saved_tab_widget): - """Callback on any tab widget save.""" - return - - def _save(self): - self.set_state(CategoryState.Working) - - if self.items_are_valid(): - self.save() - - self._update_values() - - self.set_state(CategoryState.Idle) - - self.saved.emit(self) - - def _on_refresh(self): - self.reset() - - def _on_hide_studio_overrides(self, state): - self._hide_studio_overrides = (state == QtCore.Qt.Checked) - self._update_values() - - def _save_as_defaults(self): - if not self.items_are_valid(): - return - - all_values = {} - for item in self.input_fields: - all_values.update(item.config_value()) - - for key in reversed(self.keys): - all_values = {key: all_values} - - # Skip first key and convert data to store - all_values = lib.convert_gui_data_with_metadata( - all_values[self.main_schema_key] - ) - - if not self.validate_defaults_to_save(all_values): - return - - defaults_dir = self.defaults_dir() - keys_to_file = lib.file_keys_from_schema(self.schema) - for key_sequence in keys_to_file: - # Skip first key - key_sequence = key_sequence[1:] - subpath = "/".join(key_sequence) + ".json" - - new_values = all_values - for key in key_sequence: - new_values = new_values[key] - - output_path = os.path.join(defaults_dir, subpath) - dirpath = os.path.dirname(output_path) - if not os.path.exists(dirpath): - os.makedirs(dirpath) - - print("Saving data to: ", subpath) - with open(output_path, "w") as file_stream: - json.dump(new_values, file_stream, indent=4) - - reset_default_settings() - - self._update_values() - - def _update_values(self): - self.ignore_value_changes = True - self.update_values() - self.ignore_value_changes = False - - def add_children_gui(self, child_configuration): - klass = lib.TypeToKlass.types.get(child_configuration["type"]) - item = klass(child_configuration, self) - item.create_ui() - self.input_fields.append(item) - self.content_layout.addWidget(item, 0) - - # Add spacer to stretch children guis - self.content_layout.addWidget( - QtWidgets.QWidget(self.content_widget), 1 - ) - - -class IgnoreInputChangesObj: - def __init__(self, top_widget): - self._ignore_changes = False - self.top_widget = top_widget - - def __bool__(self): - return self._ignore_changes - - def set_ignore(self, ignore_changes=True): - if self._ignore_changes == ignore_changes: - return - self._ignore_changes = ignore_changes - if not ignore_changes: - self.top_widget.hierarchical_style_update() - - -class SystemWidget(SettingsCategoryWidget): - schema_category = "system_schema" - initial_schema_name = "schema_main" - - def initialize_attributes(self, *args, **kwargs): - self._hide_studio_overrides = False - self.ignore_input_changes = IgnoreInputChangesObj(self) - - self.keys = [] - self.input_fields = [] - - def defaults_dir(self): - print("*** defaults_dir") - - def validate_defaults_to_save(self, values): - print("*** validate_defaults_to_save") - - def trigger_hierarchical_style_update(self): - self.hierarchical_style_update() - - def items_are_valid(self): - invalid_items = self.get_invalid() - if not invalid_items: - return True - - msg_box = QtWidgets.QMessageBox( - QtWidgets.QMessageBox.Warning, - "Invalid input", - "There is invalid value in one of inputs." - " Please lead red color and fix them.", - parent=self - ) - msg_box.setStandardButtons(QtWidgets.QMessageBox.Ok) - msg_box.exec_() - - first_invalid_item = invalid_items[0] - self.scroll_widget.ensureWidgetVisible(first_invalid_item) - if first_invalid_item.isVisible(): - first_invalid_item.setFocus(True) - return False - - def save(self): - if self.items_are_valid(): - self.entity.save() - # NOTE There are relations to previous entities and C++ callbacks - # so it is easier to just use new entity and recreate UI but - # would be nice to change this and add cleanup part so this is - # not required. - self.reset() - - def get_invalid(self): - invalid = [] - for input_field in self.input_fields: - invalid.extend(input_field.get_invalid()) - return invalid - - def update_values(self): - # TODO remove as it breaks entities. Was used in previous - # implementation of category widget. - pass - def create_ui(self): self.modify_defaults_checkbox = None @@ -552,6 +215,9 @@ class SystemWidget(SettingsCategoryWidget): self.ui_tweaks() + def ui_tweaks(self): + return + def _add_developer_ui(self, footer_layout): refresh_icon = qtawesome.icon("fa.refresh", color="white") refresh_button = QtWidgets.QPushButton() @@ -577,13 +243,42 @@ class SystemWidget(SettingsCategoryWidget): ) self.modify_defaults_checkbox = modify_defaults_checkbox - def _on_modify_defaults(self): - if self.modify_defaults_checkbox.isChecked(): - if not self.entity.is_in_defaults_state(): - self.reset() - else: - if not self.entity.is_in_studio_state(): - self.reset() + def get_invalid(self): + invalid = [] + for input_field in self.input_fields: + invalid.extend(input_field.get_invalid()) + return invalid + + def hierarchical_style_update(self): + for input_field in self.input_fields: + input_field.hierarchical_style_update() + + def trigger_hierarchical_style_update(self): + self.hierarchical_style_update() + + def _on_entity_change(self): + self.hierarchical_style_update() + + def add_widget_to_layout(self, widget, label_widget=None): + if label_widget: + raise NotImplementedError( + "`add_widget_to_layout` on Category item can't accept labels" + ) + self.content_layout.addWidget(widget, 0) + + def save(self): + if self.items_are_valid(): + self.entity.save() + # NOTE There are relations to previous entities and C++ callbacks + # so it is easier to just use new entity and recreate UI but + # would be nice to change this and add cleanup part so this is + # not required. + self.reset() + + def _create_root_entity(self): + raise NotImplementedError( + "`create_root_entity` method not implemented" + ) def reset(self): self.set_state(CategoryState.Working) @@ -596,6 +291,73 @@ class SystemWidget(SettingsCategoryWidget): self.content_layout.removeWidget(widget) widget.deleteLater() + self._create_root_entity() + + self.add_children_gui() + + self.ignore_input_changes.set_ignore(True) + + for input_field in self.input_fields: + input_field.set_entity_value() + + self.ignore_input_changes.set_ignore(False) + + self.set_state(CategoryState.Idle) + + def add_children_gui(self): + for child_obj in self.entity.children: + item = self.create_ui_for_entity(child_obj, self) + self.input_fields.append(item) + + # Add spacer to stretch children guis + self.content_layout.addWidget( + QtWidgets.QWidget(self.content_widget), 1 + ) + + def items_are_valid(self): + invalid_items = self.get_invalid() + if not invalid_items: + return True + + msg_box = QtWidgets.QMessageBox( + QtWidgets.QMessageBox.Warning, + "Invalid input", + "There is invalid value in one of inputs." + " Please lead red color and fix them.", + parent=self + ) + msg_box.setStandardButtons(QtWidgets.QMessageBox.Ok) + msg_box.exec_() + + first_invalid_item = invalid_items[0] + self.scroll_widget.ensureWidgetVisible(first_invalid_item) + if first_invalid_item.isVisible(): + first_invalid_item.setFocus(True) + return False + + def on_saved(self, saved_tab_widget): + """Callback on any tab widget save.""" + return + + def _save(self): + self.set_state(CategoryState.Working) + + if self.items_are_valid(): + self.save() + + self.set_state(CategoryState.Idle) + + self.saved.emit(self) + + def _on_refresh(self): + self.reset() + + def _on_hide_studio_overrides(self, state): + self._hide_studio_overrides = (state == QtCore.Qt.Checked) + + +class SystemWidget(SettingsCategoryWidget): + def _create_root_entity(self): self.entity = SystemSettings(set_studio_state=False) self.entity.on_change_callbacks.append(self._on_entity_change) try: @@ -622,51 +384,19 @@ class SystemWidget(SettingsCategoryWidget): self.modify_defaults_checkbox.setChecked(True) self.modify_defaults_checkbox.setEnabled(False) - self.add_children_gui() - - self.ignore_input_changes.set_ignore(True) - - for input_field in self.input_fields: - input_field.set_entity_value() - - self.ignore_input_changes.set_ignore(False) - - self.set_state(CategoryState.Idle) - - def _on_entity_change(self): - self.hierarchical_style_update() - - def hierarchical_style_update(self): - for input_field in self.input_fields: - input_field.hierarchical_style_update() - - def add_widget_to_layout(self, widget, label_widget=None): - if label_widget: - raise NotImplementedError( - "`add_widget_to_layout` is not implemented on Category item" - ) - self.content_layout.addWidget(widget, 0) - - def add_children_gui(self): - for child_obj in self.entity.children: - item = self.create_ui_for_entity(child_obj, self) - self.input_fields.append(item) - - # Add spacer to stretch children guis - self.content_layout.addWidget( - QtWidgets.QWidget(self.content_widget), 1 - ) + def _on_modify_defaults(self): + if self.modify_defaults_checkbox.isChecked(): + if not self.entity.is_in_defaults_state(): + self.reset() + else: + if not self.entity.is_in_studio_state(): + self.reset() class ProjectWidget(SettingsCategoryWidget): - schema_category = "projects_schema" - initial_schema_name = "schema_main" - def initialize_attributes(self): self.project_name = None - super(ProjectWidget, self).initialize_attributes() - def ui_tweaks(self): project_list_widget = ProjectListWidget(self) project_list_widget.refresh() @@ -677,13 +407,6 @@ class ProjectWidget(SettingsCategoryWidget): self.project_list_widget = project_list_widget - def defaults_dir(self): - return DEFAULTS_DIR - - def validate_defaults_to_save(self, _): - # Projects does not have any specific validations - return True - def on_saved(self, saved_tab_widget): """Callback on any tab widget save. @@ -701,82 +424,55 @@ class ProjectWidget(SettingsCategoryWidget): if mongo_url != os.environ["AVALON_MONGO"]: self.project_list_widget.refresh() + def _create_root_entity(self): + self.entity = ProjectSettings(change_state=False) + self.entity.on_change_callbacks.append(self._on_entity_change) + try: + if ( + self.modify_defaults_checkbox + and self.modify_defaults_checkbox.isChecked() + ): + self.entity.set_defaults_state() + + elif self.project_name is None: + self.entity.set_studio_state() + + else: + self.entity.change_project(self.project_name) + self.entity.set_project_state() + + if self.modify_defaults_checkbox: + self.modify_defaults_checkbox.setEnabled(True) + + except DefaultsNotDefined: + if not self.modify_defaults_checkbox: + msg_box = QtWidgets.QMessageBox( + "BUG: Default values are not set and you" + " don't have permissions to modify them." + ) + msg_box.exec_() + return + + self.entity.set_defaults_state() + self.modify_defaults_checkbox.setChecked(True) + self.modify_defaults_checkbox.setEnabled(False) + def _on_project_change(self): self.set_state(CategoryState.Working) project_name = self.project_list_widget.project_name() - if project_name is None: - _project_overrides = lib.NOT_SET - _project_anatomy = lib.NOT_SET - self.is_overidable = False - else: - _project_overrides = get_project_settings_overrides(project_name) - _project_anatomy = get_project_anatomy_overrides(project_name) - self.is_overidable = True + if project_name == self.project_name: + return - overrides = {self.main_schema_key: { - PROJECT_SETTINGS_KEY: lib.convert_overrides_to_gui_data( - _project_overrides - ), - PROJECT_ANATOMY_KEY: lib.convert_overrides_to_gui_data( - _project_anatomy - ) - }} - self.project_name = project_name - self.ignore_value_changes = True - for item in self.input_fields: - item.apply_overrides(overrides) - self.ignore_value_changes = False + self.entity.change_project(project_name) + self.reset() self.set_state(CategoryState.Idle) - def save(self): - data = {} - studio_overrides = bool(self.project_name is None) - for item in self.input_fields: - if studio_overrides: - value, _is_group = item.studio_overrides() - else: - value, _is_group = item.overrides() - if value is not lib.NOT_SET: - data.update(value) - - output_data = lib.convert_gui_data_to_overrides( - data.get(self.main_schema_key) or {} - ) - - # Saving overrides data - project_overrides_data = output_data.get(PROJECT_SETTINGS_KEY, {}) - save_project_settings(self.project_name, project_overrides_data) - - # Saving anatomy data - project_anatomy_data = output_data.get(PROJECT_ANATOMY_KEY, {}) - save_project_anatomy(self.project_name, project_anatomy_data) - - def update_values(self): - if self.project_name is not None: - self._on_project_change() - return - - default_values = lib.convert_data_to_gui_data( - {self.main_schema_key: get_default_settings()} - ) - for input_field in self.input_fields: - input_field.update_default_values(default_values) - - if self._hide_studio_overrides: - studio_values = lib.NOT_SET + def _on_modify_defaults(self): + if self.modify_defaults_checkbox.isChecked(): + if not self.entity.is_in_defaults_state(): + self.reset() else: - studio_values = lib.convert_overrides_to_gui_data({ - self.main_schema_key: { - PROJECT_SETTINGS_KEY: ( - get_studio_project_settings_overrides() - ), - PROJECT_ANATOMY_KEY: ( - get_studio_project_anatomy_overrides() - ) - } - }) - - for input_field in self.input_fields: - input_field.update_studio_values(studio_values) + if not self.entity.is_in_studio_state(): + self.reset() From e4005578d7e5f569afede52ee4f1563598239674 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 14:17:15 +0100 Subject: [PATCH 13/83] Added MockUp widget for testing purposes --- pype/tools/settings/settings/widgets/base.py | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pype/tools/settings/settings/widgets/base.py b/pype/tools/settings/settings/widgets/base.py index 75897196b0..aaeb736c0a 100644 --- a/pype/tools/settings/settings/widgets/base.py +++ b/pype/tools/settings/settings/widgets/base.py @@ -265,3 +265,28 @@ class GUIWidget(BaseWidget): def get_invalid(self): return [] + + +class MockUpWidget(BaseWidget): + allow_actions = False + child_invalid = False + + def create_ui(self): + self.setObjectName("LabelWidget") + + label = "Mockup widget for entity {}".format(self.entity.path) + label_widget = QtWidgets.QLabel(label, self) + + layout = QtWidgets.QHBoxLayout(self) + layout.setContentsMargins(0, 5, 0, 5) + layout.addWidget(label_widget) + self.entity_widget.add_widget_to_layout(self) + + def set_entity_value(self): + return + + def hierarchical_style_update(self): + pass + + def get_invalid(self): + return [] From bcdc773522ebd7a57304754f02123a1e80a754d3 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 14:17:27 +0100 Subject: [PATCH 14/83] fix attribute access --- pype/tools/settings/settings/widgets/item_widgets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/tools/settings/settings/widgets/item_widgets.py b/pype/tools/settings/settings/widgets/item_widgets.py index 6f8441581d..c4918a3f9a 100644 --- a/pype/tools/settings/settings/widgets/item_widgets.py +++ b/pype/tools/settings/settings/widgets/item_widgets.py @@ -87,7 +87,7 @@ class DictImmutableKeysWidget(BaseWidget): if self.entity.is_dynamic_item: content_widget.setObjectName("DictAsWidgetBody") - show_borders = str(int(self.show_borders)) + show_borders = str(int(self.entity.show_borders)) content_widget.setProperty("show_borders", show_borders) content_layout_margins = (5, 5, 5, 5) main_layout_spacing = 5 From cde534d1063ba04de9a6158caf7607cee159e324 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 14:23:56 +0100 Subject: [PATCH 15/83] fixed project change validation --- pype/tools/settings/settings/widgets/widgets.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pype/tools/settings/settings/widgets/widgets.py b/pype/tools/settings/settings/widgets/widgets.py index 9c0e58d52a..ad0895758f 100644 --- a/pype/tools/settings/settings/widgets/widgets.py +++ b/pype/tools/settings/settings/widgets/widgets.py @@ -610,12 +610,7 @@ class ProjectListWidget(QtWidgets.QWidget): self.select_project(self.current_project) def validate_context_change(self): - # TODO add check if project can be changed (is modified) - for item in self._parent.input_fields: - is_modified = item.child_modified - if is_modified: - return False - return True + return not self._parent.entity.has_unsaved_changes def project_name(self): if self.current_project == self.default: From 59fc8e452235ff6cf6769177194c31e8d108d371 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 14:24:14 +0100 Subject: [PATCH 16/83] moved set state after validations --- pype/tools/settings/settings/widgets/categories.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index d2e3ce0d1a..5483e485a2 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -458,12 +458,12 @@ class ProjectWidget(SettingsCategoryWidget): self.modify_defaults_checkbox.setEnabled(False) def _on_project_change(self): - self.set_state(CategoryState.Working) - project_name = self.project_list_widget.project_name() if project_name == self.project_name: return + self.set_state(CategoryState.Working) + self.entity.change_project(project_name) self.reset() From a1686e5230c176da422be7f40fe6558481c7e59c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 14:24:45 +0100 Subject: [PATCH 17/83] Anatomy is group entity now --- .../entities/schemas/projects_schema/schema_main.json | 2 ++ .../projects_schema/schemas/schema_anatomy_imageio.json | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pype/settings/entities/schemas/projects_schema/schema_main.json b/pype/settings/entities/schemas/projects_schema/schema_main.json index 51371b8cfd..9a62164cea 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_main.json +++ b/pype/settings/entities/schemas/projects_schema/schema_main.json @@ -5,6 +5,8 @@ { "type": "anatomy", "key": "project_anatomy", + "label": "Anatomy", + "is_group": true, "children": [ { "key": "roots", diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json index 2c8b1b213a..3242b6536e 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json @@ -88,7 +88,6 @@ "type": "dict", "label": "Colorspace on Inputs by regex detection", "collapsable": true, - "is_group": true, "children": [ { "type": "list", @@ -123,7 +122,6 @@ "type": "dict", "label": "Workfile", "collapsable": false, - "is_group": true, "children": [ { "type": "form", @@ -221,7 +219,6 @@ "type": "dict", "label": "Nodes", "collapsable": true, - "is_group": true, "children": [ { "key": "requiredNodes", @@ -325,7 +322,6 @@ "key": "regexInputs", "type": "dict", "label": "Colorspace on Inputs by regex detection", - "is_group": true, "collapsable": true, "children": [ { From 715afc209ccd8f04bf7e93c0f9aed5704cb52aa2 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 14:48:12 +0100 Subject: [PATCH 18/83] modify validations method for project settings --- pype/settings/entities/root_entities.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index 1b5c7e4253..a458018f06 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -644,7 +644,7 @@ class ProjectSettings(RootEntity): def _save_studio_values(self): settings_value = self.settings_value() - self._validate_duplicated_env_group(settings_value) + self._validate_values_to_save(settings_value) self.log.debug("Saving system settings: {}".format( json.dumps(settings_value, indent=4) @@ -655,6 +655,9 @@ class ProjectSettings(RootEntity): """Valiations of default values before save.""" pass + def _validate_values_to_save(self, value): + pass + def _save_project_values(self): """System settings can't have project overrides. From 219a5540ff143dd26954952e00f35524f7be8d92 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 14:58:08 +0100 Subject: [PATCH 19/83] fix import in inputs --- pype/settings/entities/input_entities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/settings/entities/input_entities.py b/pype/settings/entities/input_entities.py index d64b697428..ce512519a1 100644 --- a/pype/settings/entities/input_entities.py +++ b/pype/settings/entities/input_entities.py @@ -1,7 +1,7 @@ import copy from abc import abstractmethod -from .item_entities import ItemEntity +from .base_entity import ItemEntity from .lib import ( NOT_SET, OverrideState From 5c5035d1a49b406381791b7c5c261d211cde8bf2 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 14:58:23 +0100 Subject: [PATCH 20/83] add settings value validation to strict list --- pype/settings/entities/item_entities.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pype/settings/entities/item_entities.py b/pype/settings/entities/item_entities.py index acadec1ed3..2fec667749 100644 --- a/pype/settings/entities/item_entities.py +++ b/pype/settings/entities/item_entities.py @@ -231,6 +231,20 @@ class ListStrictEntity(ItemEntity): self.children[idx].set(item) def settings_value(self): + if self._override_state is OverrideState.NOT_DEFINED: + return NOT_SET + + if ( + self.is_group + and self._override_state is not OverrideState.DEFAULTS + ): + if self._override_state is OverrideState.STUDIO: + if not self.has_studio_override: + return NOT_SET + elif self._override_state is OverrideState.PROJECT: + if not self.has_project_override: + return NOT_SET + output = [] for child_obj in self.children: output.append(child_obj.settings_value()) From c6ebcd3233394e9274026562bf3bda0ad4ea132e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 15:09:30 +0100 Subject: [PATCH 21/83] added groups on each anatomy item instead of anatomy itself --- .../settings/entities/schemas/projects_schema/schema_main.json | 2 +- .../projects_schema/schemas/schema_anatomy_attributes.json | 1 + .../projects_schema/schemas/schema_anatomy_imageio.json | 1 + .../projects_schema/schemas/schema_anatomy_templates.json | 3 ++- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pype/settings/entities/schemas/projects_schema/schema_main.json b/pype/settings/entities/schemas/projects_schema/schema_main.json index 9a62164cea..8ad059f1c7 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_main.json +++ b/pype/settings/entities/schemas/projects_schema/schema_main.json @@ -6,13 +6,13 @@ "type": "anatomy", "key": "project_anatomy", "label": "Anatomy", - "is_group": true, "children": [ { "key": "roots", "label": "Roots", "type": "anatomy_roots", "is_file": true, + "is_group": true, "expandable": false, "object_type": { "type": "path-widget", diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json index b045ef978b..3e85c422e1 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json @@ -4,6 +4,7 @@ "key": "attributes", "label": "Attributes", "is_file": true, + "is_group": true, "children": [ { "type": "number", diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json index 3242b6536e..8f7d2cc283 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json @@ -3,6 +3,7 @@ "key": "imageio", "label": "Color Management and Output Formats", "is_file": true, + "is_group": true, "children": [ { "key": "hiero", diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json index 1f545f14be..cffb760374 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json @@ -1,10 +1,11 @@ { "type": "dict", - "collapsable": true, "key": "templates", "label": "Templates", + "collapsable": true, "collapsable_key": true, "is_file": true, + "is_group": true, "children": [ { "type": "number", From 15cd66c0a6887a568e582e976acf6205b264f44c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 15:12:38 +0100 Subject: [PATCH 22/83] added schema validations to root entity --- pype/settings/entities/root_entities.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index a458018f06..e94d7c975d 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -142,8 +142,16 @@ class RootEntity(BaseItemEntity): self._add_children(self.schema_data) - for children in self.children: - children.schema_validations() + self.schema_validations() + + def schema_validations(self): + for child_entity in self.children: + if child_entity.is_group: + raise ValueError(( + "Root entity \"{}\" has child with `is_group`" + " attribute set to True but root can't save overrides." + ).format(self.__class__.__name__)) + child_entity.schema_validations() def create_schema_object(self, schema_data, *args, **kwargs): """Create entity by entered schema data. From b38f946a330cfecc98f20777c1952c5460de31b1 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 15:14:20 +0100 Subject: [PATCH 23/83] removed ftrack project schemas --- .../ftrack/project_schemas/default.json | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 pype/settings/defaults/project_settings/ftrack/project_schemas/default.json diff --git a/pype/settings/defaults/project_settings/ftrack/project_schemas/default.json b/pype/settings/defaults/project_settings/ftrack/project_schemas/default.json deleted file mode 100644 index a90a0b3a8b..0000000000 --- a/pype/settings/defaults/project_settings/ftrack/project_schemas/default.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "object_types": ["Milestone", "Task", "Folder", "Asset Build", "Shot", "Library", "Sequence"], - "version_workflow": ["Pending Review", "Client Review", "On Farm", "Reviewed", "Render Complete", "Approved", "CBB", "Delivered", "Render Failed", "data"], - "task_workflow": ["Not Ready", "Ready", "Change Requested", "In progress", "Pending Review", "On Farm", "Waiting", "Render Complete", "Complete", "CBB", "On Hold", "Render Failed", "Omitted"], - "overrides": [{ - "task_types": ["Animation"], - "statuses": ["Not Ready", "Ready", "Change Requested", "Blocking", "Animating", "blocking review", "anim review", "Complete", "CBB", "On Hold", "Omitted"] - }, { - "task_types": ["Lighting"], - "statuses": ["Not Ready", "Ready", "Change Requested", "In progress", "To render", "On Farm", "Render Complete", "Complete", "CBB", "On Hold", "Render Failed", "Omitted"] - }], - "task_type_schema": ["Layout", "Animation", "Modeling", "Previz", "Lookdev", "FX", "Lighting", "Compositing", "Rigging", "Texture", "Matte-paint", "Roto-paint", "Art", "Match-moving", "Production", "Build", "Setdress", "Edit", "R&D", "Boards"], - "schemas": [{ - "object_type": "Shot", - "statuses": ["Omitted", "Normal", "Complete"], - "task_types": [] - }, { - "object_type": "Asset Build", - "statuses": ["Omitted", "Normal", "Complete"], - "task_types": ["Setups", "Sets", "Characters", "Props", "Locations", "Assembly", "R&D", "Elements"] - }, { - "object_type": "Milestone", - "statuses": ["Normal", "Complete"], - "task_types": ["Generic"] - }], - "task_templates": [{ - "name": "Character", - "task_types": ["Art", "Modeling", "Lookdev", "Rigging"] - }, { - "name": "Element", - "task_types": ["Modeling", "Lookdev"] - }, { - "name": "Prop", - "task_types": ["Modeling", "Lookdev", "Rigging"] - }, { - "name": "Location", - "task_types": ["Layout", "Setdress"] - }] -} \ No newline at end of file From 0970ca7f1023cc483d165a649ab9be06d2a51a10 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 15:15:05 +0100 Subject: [PATCH 24/83] log entity path when keys are unknown --- pype/settings/entities/dict_immutable_keys_entity.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pype/settings/entities/dict_immutable_keys_entity.py b/pype/settings/entities/dict_immutable_keys_entity.py index c6ed41c402..9379d43325 100644 --- a/pype/settings/entities/dict_immutable_keys_entity.py +++ b/pype/settings/entities/dict_immutable_keys_entity.py @@ -396,7 +396,8 @@ class DictImmutableKeysEntity(ItemEntity): unknown_keys = value_keys - expected_keys if unknown_keys: self.log.warning( - "Unknown keys in default values: {}".format( + "{} Unknown keys in default values: {}".format( + self.path, ", ".join("\"{}\"".format(key) for key in unknown_keys) ) ) @@ -424,7 +425,8 @@ class DictImmutableKeysEntity(ItemEntity): unknown_keys = value_keys - expected_keys if unknown_keys: self.log.warning( - "Unknown keys in studio overrides: {}".format( + "{} Unknown keys in studio overrides: {}".format( + self.path, ", ".join("\"{}\"".format(key) for key in unknown_keys) ) ) @@ -451,7 +453,8 @@ class DictImmutableKeysEntity(ItemEntity): unknown_keys = value_keys - expected_keys if unknown_keys: self.log.warning( - "Unknown keys in project overrides: {}".format( + "{} Unknown keys in project overrides: {}".format( + self.path, ", ".join("\"{}\"".format(key) for key in unknown_keys) ) ) From 00ce7e38abd63169cfbdbc403751fc520d23f1f6 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 15:18:15 +0100 Subject: [PATCH 25/83] removed item_types and anatomy_types --- .../settings/settings/widgets/__init__.py | 7 +- .../settings/widgets/anatomy_types.py | 574 --- .../settings/settings/widgets/item_types.py | 4129 ----------------- 3 files changed, 2 insertions(+), 4708 deletions(-) delete mode 100644 pype/tools/settings/settings/widgets/anatomy_types.py delete mode 100644 pype/tools/settings/settings/widgets/item_types.py diff --git a/pype/tools/settings/settings/widgets/__init__.py b/pype/tools/settings/settings/widgets/__init__.py index 653e0d0ac8..c9fec16f6e 100644 --- a/pype/tools/settings/settings/widgets/__init__.py +++ b/pype/tools/settings/settings/widgets/__init__.py @@ -1,11 +1,8 @@ from .window import MainWidget from .widgets import ProjectListWidget -from . import item_types -from . import anatomy_types + __all__ = [ "MainWidget", - "ProjectListWidget", - "item_types", - "anatomy_types" + "ProjectListWidget" ] diff --git a/pype/tools/settings/settings/widgets/anatomy_types.py b/pype/tools/settings/settings/widgets/anatomy_types.py deleted file mode 100644 index 556718a161..0000000000 --- a/pype/tools/settings/settings/widgets/anatomy_types.py +++ /dev/null @@ -1,574 +0,0 @@ -from Qt import QtWidgets, QtCore -from .widgets import ExpandingWidget -from .item_types import ( - SettingObject, - ModifiableDict, - PathWidget, - RawJsonWidget, - DictWidget -) -from .lib import NOT_SET, TypeToKlass, CHILD_OFFSET, METADATA_KEY - - -class AnatomyWidget(QtWidgets.QWidget, SettingObject): - value_changed = QtCore.Signal(object) - template_keys = ( - "project[name]", - "project[code]", - "asset", - "task", - "subset", - "family", - "version", - "ext", - "representation" - ) - default_exmaple_data = { - "project": { - "name": "ProjectPype", - "code": "pp", - }, - "asset": "sq01sh0010", - "task": "compositing", - "subset": "renderMain", - "family": "render", - "version": 1, - "ext": ".png", - "representation": "png" - } - - def __init__(self, schema_data, parent, as_widget=False): - if as_widget: - raise TypeError( - "`AnatomyWidget` does not allow to be used as widget." - ) - super(AnatomyWidget, self).__init__(parent) - self.setObjectName("AnatomyWidget") - - self.initial_attributes(schema_data, parent, as_widget) - - self.input_fields = [] - - self.key = schema_data["key"] - - def create_ui(self, label_widget=None): - children_data = self.schema_data["children"] - for schema_data in children_data: - item = TypeToKlass.types[schema_data["type"]](schema_data, self) - item.create_ui() - self.input_fields.append(item) - - self.setAttribute(QtCore.Qt.WA_StyledBackground) - - body_widget = ExpandingWidget("Anatomy", self) - - layout = QtWidgets.QVBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(0) - layout.addWidget(body_widget) - - content_widget = QtWidgets.QWidget(body_widget) - content_layout = QtWidgets.QVBoxLayout(content_widget) - content_layout.setContentsMargins(CHILD_OFFSET, 5, 0, 0) - content_layout.setSpacing(5) - - for input_field in self.input_fields: - content_layout.addWidget(input_field) - input_field.value_changed.connect(self._on_value_change) - - body_widget.set_content_widget(content_widget) - - self.body_widget = body_widget - self.label_widget = body_widget.label_widget - - def update_default_values(self, parent_values): - self._state = None - self._child_state = None - - if isinstance(parent_values, dict): - value = parent_values.get(self.key, NOT_SET) - else: - value = NOT_SET - - for input_field in self.input_fields: - input_field.update_default_values(value) - - def update_studio_values(self, parent_values): - self._state = None - self._child_state = None - - if isinstance(parent_values, dict): - value = parent_values.get(self.key, NOT_SET) - else: - value = NOT_SET - - for input_field in self.input_fields: - input_field.update_studio_values(value) - - def apply_overrides(self, parent_values): - # Make sure this is set to False - self._state = None - self._child_state = None - - value = NOT_SET - if parent_values is not NOT_SET: - value = parent_values.get(self.key, value) - - for input_field in self.input_fields: - input_field.apply_overrides(value) - - def set_value(self, value): - raise TypeError("AnatomyWidget does not allow to use `set_value`") - - def _on_value_change(self, item=None): - if self.ignore_value_changes: - return - - self.hierarchical_style_update() - - self.value_changed.emit(self) - - def update_style(self, is_overriden=None): - child_has_studio_override = self.child_has_studio_override - child_modified = self.child_modified - child_invalid = self.child_invalid - child_state = self.style_state( - child_has_studio_override, - child_invalid, - self.child_overriden, - child_modified - ) - if child_state: - child_state = "child-{}".format(child_state) - - if child_state != self._child_state: - self.body_widget.side_line_widget.setProperty("state", child_state) - self.body_widget.side_line_widget.style().polish( - self.body_widget.side_line_widget - ) - self._child_state = child_state - - def hierarchical_style_update(self): - for input_field in self.input_fields: - input_field.hierarchical_style_update() - - self.update_style() - - @property - def child_has_studio_override(self): - for input_field in self.input_fields: - if input_field.child_has_studio_override: - return True - return False - - @property - def child_modified(self): - for input_field in self.input_fields: - if input_field.child_modified: - return True - return False - - @property - def child_overriden(self): - for input_field in self.input_fields: - if input_field.child_overriden: - return True - return False - - @property - def child_invalid(self): - for input_field in self.input_fields: - if input_field.child_invalid: - return True - return False - - def set_as_overriden(self): - for input_field in self.input_fields: - input_field.child_invalid.set_as_overriden() - - def remove_overrides(self): - for input_field in self.input_fields: - input_field.remove_overrides() - - def reset_to_pype_default(self): - for input_field in self.input_fields: - input_field.reset_to_pype_default() - - def set_studio_default(self): - for input_field in self.input_fields: - input_field.set_studio_default() - - def discard_changes(self): - for input_field in self.input_fields: - input_field.discard_changes() - - def overrides(self): - if self.child_overriden: - return self.config_value(), True - return NOT_SET, False - - def item_value(self): - output = {} - for input_field in self.input_fields: - output.update(input_field.config_value()) - return output - - def studio_overrides(self): - has_overrides = False - for input_field in self.input_fields: - if input_field.child_has_studio_override: - has_overrides = True - break - - if not has_overrides: - return NOT_SET, False - - groups = [] - for input_field in self.input_fields: - groups.append(input_field.key) - - value = self.config_value() - if METADATA_KEY not in value[self.key]: - value[self.key][METADATA_KEY] = {} - value[self.key][METADATA_KEY]["groups"] = groups - - return value, True - - def config_value(self): - return {self.key: self.item_value()} - - -class RootsWidget(QtWidgets.QWidget, SettingObject): - value_changed = QtCore.Signal(object) - - def __init__(self, input_data, parent): - super(RootsWidget, self).__init__(parent) - self.setObjectName("RootsWidget") - - input_data["is_group"] = True - self.initial_attributes(input_data, parent, False) - - self.key = input_data["key"] - - self.was_multiroot = NOT_SET - - def create_ui(self, _label_widget=None): - body_widget = ExpandingWidget("Roots", self) - content_widget = QtWidgets.QWidget(body_widget) - - multiroot_data = { - "key": self.key, - "expandable": False, - "object_type": { - "type": "path-widget", - "multiplatform": True - } - } - roots_widget = ModifiableDict( - multiroot_data, self, - as_widget=True, parent_widget=content_widget - ) - roots_widget.create_ui() - - content_layout = QtWidgets.QVBoxLayout(content_widget) - content_layout.setContentsMargins(0, 0, 0, 0) - content_layout.addWidget(roots_widget) - - body_widget.set_content_widget(content_widget) - self.label_widget = body_widget.label_widget - - main_layout = QtWidgets.QVBoxLayout(self) - main_layout.setContentsMargins(0, 0, 0, 0) - main_layout.addWidget(body_widget) - - self.body_widget = body_widget - self.roots_widget = roots_widget - roots_widget.value_changed.connect(self._on_value_change) - - def update_default_values(self, parent_values): - self._state = None - self._is_modified = False - - if isinstance(parent_values, dict): - value = parent_values.get(self.key, NOT_SET) - else: - value = NOT_SET - - self._has_studio_override = False - self._had_studio_override = False - - is_multiroot = True - # Backward compatibility: Allow to switch to multiroot - if isinstance(value, dict): - is_multiroot = False - for _value in value.values(): - if isinstance(_value, dict): - is_multiroot = True - break - - if not is_multiroot: - value = {"": value} - - self.roots_widget.update_default_values(value) - - def update_studio_values(self, parent_values): - self._state = None - self._is_modified = False - - if isinstance(parent_values, dict): - value = parent_values.get(self.key, NOT_SET) - else: - value = NOT_SET - - self._has_studio_override = value is not NOT_SET - self._had_studio_override = value is not NOT_SET - - self.roots_widget.update_studio_values(value) - - def apply_overrides(self, parent_values): - # Make sure this is set to False - self._state = None - self._is_modified = False - - value = NOT_SET - if parent_values is not NOT_SET: - value = parent_values.get(self.key, value) - - self._is_overriden = value is not NOT_SET - self._was_overriden = bool(self._is_overriden) - self.roots_widget.apply_overrides(value) - - def hierarchical_style_update(self): - self.roots_widget.hierarchical_style_update() - self.update_style() - - def update_style(self): - state = self.style_state( - self.has_studio_override, - self.child_invalid, - self.is_overriden, - self.is_modified - ) - if self._state == state: - return - - if state: - child_state = "child-{}".format(state) - else: - child_state = "" - - self.body_widget.side_line_widget.setProperty("state", child_state) - self.body_widget.side_line_widget.style().polish( - self.body_widget.side_line_widget - ) - - self.label_widget.setProperty("state", state) - self.label_widget.style().polish(self.label_widget) - - self._state = state - - def _on_value_change(self, item=None): - if self.ignore_value_changes: - return - - if self.is_group and self.is_overidable: - self._is_overriden = True - - self._is_modified = bool(self.child_modified) - - self.update_style() - - self.value_changed.emit(self) - - @property - def child_has_studio_override(self): - return self.roots_widget.has_studio_override - - @property - def child_modified(self): - return self.roots_widget.child_modified - - @property - def child_overriden(self): - return ( - self.roots_widget.is_overriden - or self.roots_widget.child_overriden - ) - - @property - def child_invalid(self): - return self.roots_widget.child_invalid - - def remove_overrides(self): - self._is_overriden = False - self._is_modified = False - - self.roots_widget.remove_overrides() - - def reset_to_pype_default(self): - self.roots_widget.reset_to_pype_default() - self._has_studio_override = False - - def set_studio_default(self): - self.roots_widget.reset_to_pype_default() - self._has_studio_override = True - - def discard_changes(self): - self._is_overriden = self._was_overriden - self._is_modified = False - - self.roots_widget.discard_changes() - - self._is_modified = self.child_modified - self._has_studio_override = self._had_studio_override - - def set_as_overriden(self): - self._is_overriden = True - self.roots_widget.set_as_overriden() - - def item_value(self): - return self.roots_widget.item_value() - - def config_value(self): - return {self.key: self.item_value()} - - -class TemplatesWidget(QtWidgets.QWidget, SettingObject): - value_changed = QtCore.Signal(object) - - def __init__(self, input_data, parent): - super(TemplatesWidget, self).__init__(parent) - - input_data["is_group"] = True - self.initial_attributes(input_data, parent, False) - - self.key = input_data["key"] - - def create_ui(self, label_widget=None): - body_widget = ExpandingWidget("Templates", self) - content_widget = QtWidgets.QWidget(body_widget) - body_widget.set_content_widget(content_widget) - content_layout = QtWidgets.QVBoxLayout(content_widget) - - template_input_data = { - "key": self.key - } - self.body_widget = body_widget - self.label_widget = body_widget.label_widget - self.value_input = RawJsonWidget(template_input_data, self) - self.value_input.create_ui(label_widget=self.label_widget) - - content_layout.addWidget(self.value_input) - - layout = QtWidgets.QVBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(0) - - layout.addWidget(body_widget) - - self.value_input.value_changed.connect(self._on_value_change) - - def _on_value_change(self, item): - self.update_style() - - self.value_changed.emit(self) - - def update_default_values(self, values): - self._state = None - self.value_input.update_default_values(values) - - def update_studio_values(self, values): - self._state = None - self.value_input.update_studio_values(values) - - def apply_overrides(self, parent_values): - self._state = None - self.value_input.apply_overrides(parent_values) - - def hierarchical_style_update(self): - self.value_input.hierarchical_style_update() - self.update_style() - - def update_style(self): - state = self.style_state( - self.has_studio_override, - self.child_invalid, - self.child_overriden, - self.child_modified - ) - if self._state == state: - return - - if state: - child_state = "child-{}".format(state) - else: - child_state = "" - - self.body_widget.side_line_widget.setProperty("state", child_state) - self.body_widget.side_line_widget.style().polish( - self.body_widget.side_line_widget - ) - - self.label_widget.setProperty("state", state) - self.label_widget.style().polish(self.label_widget) - - self._state = state - - @property - def is_modified(self): - return self.value_input.is_modified - - @property - def is_overriden(self): - return self._is_overriden - - @property - def has_studio_override(self): - return self.value_input._has_studio_override - - @property - def child_has_studio_override(self): - return self.value_input.child_has_studio_override - - @property - def child_modified(self): - return self.value_input.child_modified - - @property - def child_overriden(self): - return self.value_input.child_overriden - - @property - def child_invalid(self): - return self.value_input.child_invalid - - def remove_overrides(self): - self.value_input.remove_overrides() - - def reset_to_pype_default(self): - self.value_input.reset_to_pype_default() - - def set_studio_default(self): - self.value_input.set_studio_default() - - def discard_changes(self): - self.value_input.discard_changes() - - def set_as_overriden(self): - self.value_input.set_as_overriden() - - def overrides(self): - if not self.child_overriden: - return NOT_SET, False - return self.config_value(), True - - def item_value(self): - return self.value_input.item_value() - - def config_value(self): - return self.value_input.config_value() - - -TypeToKlass.types["anatomy"] = AnatomyWidget -TypeToKlass.types["anatomy_roots"] = RootsWidget -TypeToKlass.types["anatomy_templates"] = TemplatesWidget diff --git a/pype/tools/settings/settings/widgets/item_types.py b/pype/tools/settings/settings/widgets/item_types.py deleted file mode 100644 index 6ab7a03fb9..0000000000 --- a/pype/tools/settings/settings/widgets/item_types.py +++ /dev/null @@ -1,4129 +0,0 @@ -import json -import collections -from Qt import QtWidgets, QtCore, QtGui -from .widgets import ( - IconButton, - ExpandingWidget, - NumberSpinBox, - GridLabelWidget, - ComboBox, - NiceCheckbox -) -from .multiselection_combobox import MultiSelectionComboBox -from .lib import NOT_SET, METADATA_KEY, TypeToKlass, CHILD_OFFSET -from pype.api import Logger -from avalon.vendor import qtawesome - - -class InvalidValueType(Exception): - msg_template = "{}" - - def __init__(self, valid_types, invalid_type, key): - msg = "" - if key: - msg += "Key \"{}\". ".format(key) - - joined_types = ", ".join( - [str(valid_type) for valid_type in valid_types] - ) - msg += "Got invalid type \"{}\". Expected: {}".format( - invalid_type, joined_types - ) - self.msg = msg - super(InvalidValueType, self).__init__(msg) - - -class SettingObject: - """Partially abstract class for Setting's item type workflow.""" - # `is_input_type` attribute says if has implemented item type methods - is_input_type = True - # `is_wrapper_item` attribute says if item will never hold `key` - # information and is just visually different - is_wrapper_item = False - # Each input must have implemented default value for development - # when defaults are not filled yet. - default_input_value = NOT_SET - # Will allow to show actions for the item type (disabled for proxies) else - # item is skipped and try to trigger actions on it's parent. - allow_actions = True - # If item can store environment values - allow_to_environment = False - # All item types must have implemented Qt signal which is emitted when - # it's or it's children value has changed, - value_changed = None - # Item will expand to full width in grid layout - expand_in_grid = False - # types that are valid for `set_value` method - valid_value_types = tuple() - - def validate_value(self, value): - if not self.valid_value_types: - return - - for valid_type in self.valid_value_types: - if type(value) is valid_type: - return - - key = getattr(self, "key", None) - raise InvalidValueType(self.valid_value_types, type(value), key) - - def merge_metadata(self, current_metadata, new_metadata): - for key, value in new_metadata.items(): - if key not in current_metadata: - current_metadata[key] = value - - elif key == "groups": - current_metadata[key].extend(value) - - elif key == "environments": - for group_key, subvalue in value.items(): - if group_key not in current_metadata[key]: - current_metadata[key][group_key] = [] - current_metadata[key][group_key].extend(subvalue) - - else: - raise KeyError("Unknown metadata key: \"{}\"".format(key)) - return current_metadata - - def _set_default_attributes(self): - """Create and reset attributes required for all item types. - - They may not be used in the item but are required to be set. - """ - # Default input attributes - self._has_studio_override = False - self._had_studio_override = False - - self._is_overriden = False - self._was_overriden = False - - self._is_modified = False - self._is_invalid = False - - self._is_nullable = False - self._as_widget = False - self._is_group = False - self._roles = None - self.hidden_by_role = False - - # If value should be stored to environments - self._env_group_key = None - - self._any_parent_as_widget = None - self._any_parent_is_group = None - - # Parent input - self._parent = None - - # States of inputs - self._state = None - self._child_state = None - - # Attributes where values are stored - self.default_value = NOT_SET - self.studio_value = NOT_SET - self.override_value = NOT_SET - - # Log object - self._log = None - - # Only for develop mode - self.defaults_not_set = False - - def available_for_role(self, role_name=None): - if not self._roles: - return True - if role_name is None: - role_name = self.user_role - return role_name in self._roles - - def initial_attributes(self, schema_data, parent, as_widget): - """Prepare attributes based on entered arguments. - - This method should be same for each item type. Few item types - may require to extend with specific attributes for their case. - """ - self._set_default_attributes() - - self.schema_data = schema_data - - self._parent = parent - self._as_widget = as_widget - - self._roles = schema_data.get("roles") - if self._roles is not None and not isinstance(self._roles, list): - self._roles = [self._roles] - - self._is_group = schema_data.get("is_group", False) - self._env_group_key = schema_data.get("env_group_key") - # TODO not implemented yet - self._is_nullable = schema_data.get("is_nullable", False) - - if self.is_environ: - if not self.allow_to_environment: - raise TypeError(( - "Item {} does not allow to store environment values" - ).format(schema_data["type"])) - - any_parent_as_widget = parent.as_widget - if not any_parent_as_widget: - any_parent_as_widget = parent.any_parent_as_widget - - self._any_parent_as_widget = any_parent_as_widget - - any_parent_is_group = parent.is_group - if not any_parent_is_group: - any_parent_is_group = parent.any_parent_is_group - - self._any_parent_is_group = any_parent_is_group - - if not self.available_for_role(): - self.hide() - self.hidden_by_role = True - - if ( - self.is_input_type - and not self.as_widget - and not self.is_wrapper_item - ): - if "key" not in self.schema_data: - error_msg = "Missing \"key\" in schema data. {}".format( - str(schema_data).replace("'", '"') - ) - raise KeyError(error_msg) - - self.key = self.schema_data["key"] - - self.label = self.schema_data.get("label") - if not self.label and self._is_group: - raise ValueError( - "Item is set as `is_group` but has empty `label`." - ) - - @property - def user_role(self): - """Tool is running with any user role. - - Returns: - str: user role as string. - - """ - return self._parent.user_role - - @property - def log(self): - """Auto created logger for debugging.""" - if self._log is None: - self._log = Logger().get_logger(self.__class__.__name__) - return self._log - - @property - def had_studio_override(self): - """Item had studio overrides on refresh. - - Use attribute `_had_studio_override` which should be changed only - during methods `update_studio_values` and `update_default_values`. - - Returns: - bool - - """ - return self._had_studio_override - - @property - def has_studio_override(self): - """Item has studio override at the moment. - - With combination of `had_studio_override` is possible to know if item - is modified (not value change). - - Returns: - bool - - """ - return self._has_studio_override or self._parent.has_studio_override - - @property - def is_environ(self): - return self.env_group_key is not None - - @property - def env_group_key(self): - return self._env_group_key - - @env_group_key.setter - def env_group_key(self, value): - if value is not None and not isinstance(value, str): - raise TypeError( - "Expected 'None' of 'str'. Got {}".format(str(type(value))) - ) - self._env_group_key = value - - @property - def as_widget(self): - """Item is used as widget in parent item. - - Returns: - bool - - """ - return self._as_widget - - @property - def any_parent_as_widget(self): - """Any parent of item is used as widget. - - Attribute holding this information is set during creation and - stored to `_any_parent_as_widget`. - - Why is this information useful: If any parent is used as widget then - modifications and override are not important for whole part. - - Returns: - bool - - """ - if self._any_parent_as_widget is None: - return super(SettingObject, self).any_parent_as_widget - return self._any_parent_as_widget - - @property - def is_group(self): - """Item represents key that can be overriden. - - Attribute `is_group` can be set to True only once in item hierarchy. - - Returns: - bool - - """ - return self._is_group - - @property - def any_parent_is_group(self): - """Any parent of item is group. - - Attribute holding this information is set during creation and - stored to `_any_parent_is_group`. - - Why is this information useful: If any parent is group and - the parent is set as overriden, this item is overriden too. - - Returns: - bool - - """ - if self._any_parent_is_group is None: - return super(SettingObject, self).any_parent_is_group - return self._any_parent_is_group - - @property - def is_modified(self): - """Has object any changes that require saving.""" - if self.any_parent_as_widget: - return self._is_modified or self.defaults_not_set - - if self._is_modified or self.defaults_not_set: - return True - - if self.is_overidable: - if self.as_widget: - return self._was_overriden != self.is_overriden - return self.was_overriden != self.is_overriden - - return self.has_studio_override != self.had_studio_override - - @property - def is_overriden(self): - """Is object overriden so should be saved to overrides.""" - return self._is_overriden or self._parent.is_overriden - - @property - def was_overriden(self): - """Item had set value of project overrides on project change.""" - if self._as_widget: - return self._parent.was_overriden - return self._was_overriden - - @property - def is_invalid(self): - """Value set in is not valid.""" - return self._is_invalid - - @property - def is_nullable(self): - """Value of item can be set to None. - - NOT IMPLEMENTED! - """ - return self._is_nullable - - @property - def is_overidable(self): - """ care about overrides.""" - - return self._parent.is_overidable - - def any_parent_overriden(self): - """Any of parent objects up to top hiearchy item is overriden. - - Returns: - bool - - """ - - if self._parent._is_overriden: - return True - return self._parent.any_parent_overriden() - - @property - def ignore_value_changes(self): - """Most of attribute changes are ignored on value change when True.""" - return self._parent.ignore_value_changes - - @ignore_value_changes.setter - def ignore_value_changes(self, value): - """Setter for global parent item to apply changes for all inputs.""" - self._parent.ignore_value_changes = value - - def config_value(self): - """Output for saving changes or overrides.""" - return {self.key: self.item_value()} - - def environment_value(self): - raise NotImplementedError( - "{} Method `environment_value` not implemented!".format( - repr(self) - ) - ) - - @classmethod - def style_state( - cls, has_studio_override, is_invalid, is_overriden, is_modified - ): - """Return stylesheet state by intered booleans.""" - items = [] - if is_invalid: - items.append("invalid") - else: - if is_overriden: - items.append("overriden") - if is_modified: - items.append("modified") - - if not items and has_studio_override: - items.append("studio") - - return "-".join(items) or "" - - def show_actions_menu(self, event=None): - if event and event.button() != QtCore.Qt.RightButton: - return - - if not self.allow_actions: - if event: - return self.mouseReleaseEvent(event) - return - - menu = QtWidgets.QMenu(self) - - actions_mapping = {} - if self.child_modified: - action = QtWidgets.QAction("Discard changes") - actions_mapping[action] = self._discard_changes - menu.addAction(action) - - if ( - self.is_overidable - and not self.is_overriden - and not self.any_parent_is_group - ): - action = QtWidgets.QAction("Set project override") - actions_mapping[action] = self._set_as_overriden - menu.addAction(action) - - if ( - not self.is_overidable - and ( - self.has_studio_override or self.child_has_studio_override - ) - ): - action = QtWidgets.QAction("Reset to pype default") - actions_mapping[action] = self._reset_to_pype_default - menu.addAction(action) - - if ( - not self.is_overidable - and not self.is_overriden - and not self.any_parent_is_group - and not self._had_studio_override - ): - action = QtWidgets.QAction("Set studio default") - actions_mapping[action] = self._set_studio_default - menu.addAction(action) - - if ( - not self.any_parent_overriden() - and (self.is_overriden or self.child_overriden) - ): - # TODO better label - action = QtWidgets.QAction("Remove project override") - actions_mapping[action] = self._remove_overrides - menu.addAction(action) - - if not actions_mapping: - action = QtWidgets.QAction("< No action >") - actions_mapping[action] = None - menu.addAction(action) - - result = menu.exec_(QtGui.QCursor.pos()) - if result: - to_run = actions_mapping[result] - if to_run: - to_run() - - def mouseReleaseEvent(self, event): - if self.allow_actions and event.button() == QtCore.Qt.RightButton: - return self.show_actions_menu() - - mro = type(self).mro() - index = mro.index(self.__class__) - item = None - for idx in range(index + 1, len(mro)): - _item = mro[idx] - if hasattr(_item, "mouseReleaseEvent"): - item = _item - break - - if item: - return item.mouseReleaseEvent(self, event) - - def _discard_changes(self): - self.ignore_value_changes = True - self.discard_changes() - self.ignore_value_changes = False - - def discard_changes(self): - """Item's implementation to discard all changes made by user. - - Reset all values to same values as had when opened GUI - or when changed project. - - Must not affect `had_studio_override` value or `was_overriden` - value. It must be marked that there are keys/values which are not in - defaults or overrides. - """ - raise NotImplementedError( - "{} Method `discard_changes` not implemented!".format( - repr(self) - ) - ) - - def _set_studio_default(self): - self.ignore_value_changes = True - self.set_studio_default() - self.ignore_value_changes = False - - def set_studio_default(self): - """Item's implementation to set current values as studio's overrides. - - Mark item and it's children as they have studio overrides. - """ - raise NotImplementedError( - "{} Method `set_studio_default` not implemented!".format( - repr(self) - ) - ) - - def _reset_to_pype_default(self): - self.ignore_value_changes = True - self.reset_to_pype_default() - self.ignore_value_changes = False - - def reset_to_pype_default(self): - """Item's implementation to remove studio overrides. - - Mark item as it does not have studio overrides unset studio - override values. - """ - raise NotImplementedError( - "{} Method `reset_to_pype_default` not implemented!".format( - repr(self) - ) - ) - - def _remove_overrides(self): - self.ignore_value_changes = True - self.remove_overrides() - self.ignore_value_changes = False - - def remove_overrides(self): - """Item's implementation to remove project overrides. - - Mark item as does not have project overrides. Must not change - `was_overriden` attribute value. - """ - raise NotImplementedError( - "{} Method `remove_overrides` not implemented!".format( - repr(self) - ) - ) - - def _set_as_overriden(self): - self.ignore_value_changes = True - self.set_as_overriden() - self.ignore_value_changes = False - - def set_as_overriden(self): - """Item's implementation to set values as overriden for project. - - Mark item and all it's children as they're overriden. Must skip - items with children items that has attributes `is_group` - and `any_parent_is_group` set to False. In that case those items - are not meant to be overridable and should trigger the method on it's - children. - - """ - raise NotImplementedError( - "{} Method `set_as_overriden` not implemented!".format(repr(self)) - ) - - def hierarchical_style_update(self): - """Trigger update style method down the hierarchy.""" - raise NotImplementedError( - "{} Method `hierarchical_style_update` not implemented!".format( - repr(self) - ) - ) - - def update_default_values(self, parent_values): - """Fill default values on startup or on refresh. - - Default values stored in `pype` repository should update all items in - schema. Each item should take values for his key and set it's value or - pass values down to children items. - - Args: - parent_values (dict): Values of parent's item. But in case item is - used as widget, `parent_values` contain value for item. - """ - raise NotImplementedError( - "{} does not have implemented `update_default_values`".format(self) - ) - - def update_studio_values(self, parent_values): - """Fill studio override values on startup or on refresh. - - Set studio value if is not set to NOT_SET, in that case studio - overrides are not set yet. - - Args: - parent_values (dict): Values of parent's item. But in case item is - used as widget, `parent_values` contain value for item. - """ - raise NotImplementedError( - "{} does not have implemented `update_studio_values`".format(self) - ) - - def apply_overrides(self, parent_values): - """Fill project override values on startup, refresh or project change. - - Set project value if is not set to NOT_SET, in that case project - overrides are not set yet. - - Args: - parent_values (dict): Values of parent's item. But in case item is - used as widget, `parent_values` contain value for item. - """ - raise NotImplementedError( - "{} does not have implemented `apply_overrides`".format(self) - ) - - @property - def child_has_studio_override(self): - """Any children item has studio overrides.""" - raise NotImplementedError( - "{} does not have implemented `child_has_studio_override`".format( - self - ) - ) - - @property - def child_modified(self): - """Any children item is modified.""" - raise NotImplementedError( - "{} does not have implemented `child_modified`".format(self) - ) - - @property - def child_overriden(self): - """Any children item has project overrides.""" - raise NotImplementedError( - "{} does not have implemented `child_overriden`".format(self) - ) - - @property - def child_invalid(self): - """Any children item does not have valid value.""" - raise NotImplementedError( - "{} does not have implemented `child_invalid`".format(self) - ) - - def get_invalid(self): - """Return invalid item types all down the hierarchy.""" - raise NotImplementedError( - "{} does not have implemented `get_invalid`".format(self) - ) - - def item_value(self): - """Value of an item without key.""" - raise NotImplementedError( - "Method `item_value` not implemented!" - ) - - -class InputObject(SettingObject): - """Class for inputs with pre-implemented methods. - - Class is for item types not creating or using other item types, most - of methods has same code in that case. - """ - - def update_default_values(self, parent_values): - self._state = None - self._is_modified = False - - value = NOT_SET - if self.as_widget: - value = parent_values - elif parent_values is not NOT_SET: - value = parent_values.get(self.key, NOT_SET) - - if value is NOT_SET: - if self.available_for_role("developer"): - self.defaults_not_set = True - value = self.default_input_value - if value is NOT_SET: - raise NotImplementedError(( - "{} Does not have implemented" - " attribute `default_input_value`" - ).format(self)) - - else: - raise ValueError( - "Default value is not set. This is implementation BUG." - ) - else: - self.defaults_not_set = False - - self.default_value = value - self._has_studio_override = False - self._had_studio_override = False - try: - self.set_value(value) - except InvalidValueType as exc: - self.default_value = NOT_SET - self.defaults_not_set = True - self.log.warning(exc.msg) - - def update_studio_values(self, parent_values): - self._state = None - self._is_modified = False - - value = NOT_SET - if self._as_widget: - value = parent_values - elif parent_values is not NOT_SET: - value = parent_values.get(self.key, NOT_SET) - - self.studio_value = value - if value is not NOT_SET: - self._has_studio_override = True - self._had_studio_override = True - - else: - self._has_studio_override = False - self._had_studio_override = False - value = self.default_value - - try: - self.set_value(value) - except InvalidValueType as exc: - self.studio_value = NOT_SET - self.log.warning(exc.msg) - - def apply_overrides(self, parent_values): - self._is_modified = False - self._state = None - self._had_studio_override = bool(self._has_studio_override) - if self._as_widget: - override_value = parent_values - elif parent_values is NOT_SET or self.key not in parent_values: - override_value = NOT_SET - else: - override_value = parent_values[self.key] - - self.override_value = override_value - - if override_value is NOT_SET: - self._is_overriden = False - self._was_overriden = False - if self.has_studio_override: - value = self.studio_value - else: - value = self.default_value - else: - self._is_overriden = True - self._was_overriden = True - value = override_value - - try: - self.set_value(value) - except InvalidValueType as exc: - self.override_value = NOT_SET - self.log.warning(exc.msg) - - def _on_value_change(self, item=None): - if self.ignore_value_changes: - return - - if not self.any_parent_as_widget: - if self.is_overidable: - self._is_overriden = True - else: - self._has_studio_override = True - - if self._is_invalid: - self._is_modified = True - elif self._is_overriden: - self._is_modified = self.item_value() != self.override_value - elif self._has_studio_override: - self._is_modified = self.item_value() != self.studio_value - else: - self._is_modified = self.item_value() != self.default_value - - self.update_style() - - self.value_changed.emit(self) - - def studio_overrides(self): - if ( - not (self.as_widget or self.any_parent_as_widget) - and not self.has_studio_override - ): - return NOT_SET, False - return self.config_value(), self.is_group - - def overrides(self): - if ( - not (self.as_widget or self.any_parent_as_widget) - and not self.is_overriden - ): - return NOT_SET, False - return self.config_value(), self.is_group - - def hierarchical_style_update(self): - self.update_style() - - def _style_state(self): - if self.as_widget: - state = self.style_state( - False, - self._is_invalid, - False, - self.is_modified - ) - else: - state = self.style_state( - self.has_studio_override, - self.is_invalid, - self.is_overriden, - self.is_modified - ) - return state - - def update_style(self): - state = self._style_state() - if self._state == state: - return - - self._state = state - - self.input_field.setProperty("input-state", state) - self.input_field.style().polish(self.input_field) - if self.label_widget: - self.label_widget.setProperty("state", state) - self.label_widget.style().polish(self.label_widget) - - def remove_overrides(self): - self._is_overriden = False - self._is_modified = False - if self.has_studio_override: - self.set_value(self.studio_value) - else: - self.set_value(self.default_value) - self._is_overriden = False - self._is_modified = False - - def reset_to_pype_default(self): - self.set_value(self.default_value) - self._has_studio_override = False - - def set_studio_default(self): - self._has_studio_override = True - - def discard_changes(self): - self._is_overriden = self._was_overriden - self._has_studio_override = self._had_studio_override - if self.is_overidable: - if self._was_overriden and self.override_value is not NOT_SET: - self.set_value(self.override_value) - else: - if self._had_studio_override: - self.set_value(self.studio_value) - else: - self.set_value(self.default_value) - - if not self.is_overidable: - if self.has_studio_override: - self._is_modified = self.studio_value != self.item_value() - else: - self._is_modified = self.default_value != self.item_value() - self._is_overriden = False - return - - self._state = None - self._is_modified = False - self._is_overriden = self._was_overriden - - def set_as_overriden(self): - self._is_overriden = True - - @property - def child_has_studio_override(self): - return self._has_studio_override - - @property - def child_modified(self): - return self.is_modified - - @property - def child_overriden(self): - return self._is_overriden - - @property - def child_invalid(self): - return self.is_invalid - - def get_invalid(self): - output = [] - if self.is_invalid: - output.append(self) - return output - - def reset_children_attributes(self): - return - - -class BooleanWidget(QtWidgets.QWidget, InputObject): - default_input_value = True - value_changed = QtCore.Signal(object) - valid_value_types = (bool, ) - - def __init__( - self, input_data, parent, - as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(BooleanWidget, self).__init__(parent_widget) - - self.initial_attributes(input_data, parent, as_widget) - - def create_ui(self, label_widget=None): - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(5) - - if not self.as_widget and not label_widget: - label = self.schema_data["label"] - label_widget = QtWidgets.QLabel(label) - label_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground) - layout.addWidget(label_widget, 0) - self.label_widget = label_widget - - checkbox_height = self.style().pixelMetric( - QtWidgets.QStyle.PM_IndicatorHeight - ) - self.input_field = NiceCheckbox(height=checkbox_height, parent=self) - - spacer = QtWidgets.QWidget(self) - spacer.setAttribute(QtCore.Qt.WA_TranslucentBackground) - - layout.addWidget(self.input_field, 0) - layout.addWidget(spacer, 1) - - self.setFocusProxy(self.input_field) - - self.input_field.stateChanged.connect(self._on_value_change) - - def set_value(self, value): - # Ignore value change because if `self.isChecked()` has same - # value as `value` the `_on_value_change` is not triggered - self.validate_value(value) - self.input_field.setChecked(value) - - def item_value(self): - return self.input_field.isChecked() - - -class NumberWidget(QtWidgets.QWidget, InputObject): - default_input_value = 0 - value_changed = QtCore.Signal(object) - input_modifiers = ("minimum", "maximum", "decimal") - valid_value_types = (int, float) - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(NumberWidget, self).__init__(parent_widget) - - self.initial_attributes(schema_data, parent, as_widget) - - def create_ui(self, label_widget=None): - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(5) - - kwargs = { - modifier: self.schema_data.get(modifier) - for modifier in self.input_modifiers - if self.schema_data.get(modifier) - } - self.input_field = NumberSpinBox(self, **kwargs) - - self.setFocusProxy(self.input_field) - - if not self._as_widget and not label_widget: - label = self.schema_data["label"] - label_widget = QtWidgets.QLabel(label) - layout.addWidget(label_widget, 0) - self.label_widget = label_widget - - layout.addWidget(self.input_field, 1) - - self.input_field.valueChanged.connect(self._on_value_change) - - def set_value(self, value): - self.validate_value(value) - self.input_field.setValue(value) - - def item_value(self): - return self.input_field.value() - - -class TextWidget(QtWidgets.QWidget, InputObject): - default_input_value = "" - value_changed = QtCore.Signal(object) - valid_value_types = (str, ) - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(TextWidget, self).__init__(parent_widget) - - self.initial_attributes(schema_data, parent, as_widget) - self.multiline = schema_data.get("multiline", False) - self.placeholder_text = schema_data.get("placeholder") - - def create_ui(self, label_widget=None): - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(5) - - if self.multiline: - self.input_field = QtWidgets.QPlainTextEdit(self) - else: - self.input_field = QtWidgets.QLineEdit(self) - - if self.placeholder_text: - self.input_field.setPlaceholderText(self.placeholder_text) - - self.setFocusProxy(self.input_field) - - layout_kwargs = {} - if self.multiline: - layout_kwargs["alignment"] = QtCore.Qt.AlignTop - - if not self._as_widget and not label_widget: - label = self.schema_data["label"] - label_widget = QtWidgets.QLabel(label) - layout.addWidget(label_widget, 0, **layout_kwargs) - self.label_widget = label_widget - - layout.addWidget(self.input_field, 1, **layout_kwargs) - - self.input_field.textChanged.connect(self._on_value_change) - - def set_value(self, value): - self.validate_value(value) - if self.multiline: - self.input_field.setPlainText(value) - else: - self.input_field.setText(value) - - def item_value(self): - if self.multiline: - return self.input_field.toPlainText() - else: - return self.input_field.text() - - -class PathInputWidget(QtWidgets.QWidget, InputObject): - default_input_value = "" - value_changed = QtCore.Signal(object) - valid_value_types = (str, list) - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(PathInputWidget, self).__init__(parent_widget) - - self.initial_attributes(schema_data, parent, as_widget) - - self.with_arguments = schema_data.get("with_arguments", False) - - def create_ui(self, label_widget=None): - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(5) - - if not self._as_widget and not label_widget: - label = self.schema_data["label"] - label_widget = QtWidgets.QLabel(label) - layout.addWidget(label_widget, 0) - self.label_widget = label_widget - - self.input_field = QtWidgets.QLineEdit(self) - self.args_input_field = None - if self.with_arguments: - self.input_field.setPlaceholderText("Executable path") - self.args_input_field = QtWidgets.QLineEdit(self) - self.args_input_field.setPlaceholderText("Arguments") - - self.setFocusProxy(self.input_field) - layout.addWidget(self.input_field, 8) - self.input_field.textChanged.connect(self._on_value_change) - - if self.args_input_field: - layout.addWidget(self.args_input_field, 2) - self.args_input_field.textChanged.connect(self._on_value_change) - - def set_value(self, value): - self.validate_value(value) - - if not isinstance(value, list): - self.input_field.setText(value) - elif self.with_arguments: - self.input_field.setText(value[0]) - self.args_input_field.setText(value[1]) - else: - self.input_field.setText(value[0]) - - def item_value(self): - path_value = self.input_field.text() - if self.with_arguments: - return [path_value, self.args_input_field.text()] - return path_value - - -class EnumeratorWidget(QtWidgets.QWidget, InputObject): - default_input_value = True - value_changed = QtCore.Signal(object) - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(EnumeratorWidget, self).__init__(parent_widget) - - self.initial_attributes(schema_data, parent, as_widget) - self.multiselection = schema_data.get("multiselection") - self.enum_items = schema_data["enum_items"] - if not self.enum_items: - raise ValueError("Attribute `enum_items` is not defined.") - - def create_ui(self, label_widget=None): - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(5) - - if not self._as_widget and not label_widget: - label = self.schema_data["label"] - label_widget = QtWidgets.QLabel(label) - label_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground) - layout.addWidget(label_widget, 0) - self.label_widget = label_widget - - if self.multiselection: - placeholder = self.schema_data.get("placeholder") - self.input_field = MultiSelectionComboBox( - placeholder=placeholder, parent=self - ) - else: - self.input_field = ComboBox(self) - - first_value = NOT_SET - for enum_item in self.enum_items: - for value, label in enum_item.items(): - if first_value is NOT_SET: - first_value = value - self.input_field.addItem(label, value) - self._first_value = first_value - - if self.multiselection: - model = self.input_field.model() - for idx in range(self.input_field.count()): - model.item(idx).setCheckable(True) - - layout.addWidget(self.input_field, 0) - - self.setFocusProxy(self.input_field) - - self.input_field.value_changed.connect(self._on_value_change) - - @property - def default_input_value(self): - if self.multiselection: - return [] - return self._first_value - - def set_value(self, value): - # Ignore value change because if `self.isChecked()` has same - # value as `value` the `_on_value_change` is not triggered - self.input_field.set_value(value) - - def update_style(self): - if self.as_widget: - state = self.style_state( - False, - self._is_invalid, - False, - self._is_modified - ) - else: - state = self.style_state( - self.has_studio_override, - self.is_invalid, - self.is_overriden, - self.is_modified - ) - - if self._state == state: - return - - self._state = state - self.input_field.setProperty("input-state", state) - self.input_field.style().polish(self.input_field) - if self.label_widget: - self.label_widget.setProperty("state", state) - self.label_widget.style().polish(self.label_widget) - - def item_value(self): - return self.input_field.value() - - -class RawJsonInput(QtWidgets.QPlainTextEdit): - tab_length = 4 - - def __init__(self, *args, **kwargs): - super(RawJsonInput, self).__init__(*args, **kwargs) - self.setObjectName("RawJsonInput") - self.setTabStopDistance( - QtGui.QFontMetricsF( - self.font() - ).horizontalAdvance(" ") * self.tab_length - ) - - def sizeHint(self): - document = self.document() - layout = document.documentLayout() - - height = document.documentMargin() + 2 * self.frameWidth() + 1 - block = document.begin() - while block != document.end(): - height += layout.blockBoundingRect(block).height() - block = block.next() - - hint = super(RawJsonInput, self).sizeHint() - hint.setHeight(height) - - return hint - - def set_value(self, value): - if value is NOT_SET: - value = "" - - elif not isinstance(value, str): - try: - value = json.dumps(value, indent=4) - except Exception: - value = "" - self.setPlainText(value) - - def json_value(self): - return json.loads(self.toPlainText()) - - def has_invalid_value(self): - try: - self.json_value() - return False - except Exception: - return True - - def resizeEvent(self, event): - self.updateGeometry() - super(RawJsonInput, self).resizeEvent(event) - - -class RawJsonWidget(QtWidgets.QWidget, InputObject): - default_input_value = "{}" - value_changed = QtCore.Signal(object) - valid_value_types = (str, dict, list, type(NOT_SET)) - allow_to_environment = True - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(RawJsonWidget, self).__init__(parent_widget) - - self.initial_attributes(schema_data, parent, as_widget) - # By default must be invalid - self._is_invalid = True - - def create_ui(self, label_widget=None): - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(5) - - self.input_field = RawJsonInput(self) - self.input_field.setSizePolicy( - QtWidgets.QSizePolicy.Minimum, - QtWidgets.QSizePolicy.MinimumExpanding - ) - - self.setFocusProxy(self.input_field) - - if not self.as_widget and not label_widget: - if self.label: - label_widget = QtWidgets.QLabel(self.label) - layout.addWidget(label_widget, 0, alignment=QtCore.Qt.AlignTop) - self.label_widget = label_widget - - layout.addWidget(self.input_field, 1, alignment=QtCore.Qt.AlignTop) - - self.input_field.textChanged.connect(self._on_value_change) - - def update_studio_values(self, parent_values): - self._is_invalid = self.input_field.has_invalid_value() - return super(RawJsonWidget, self).update_studio_values(parent_values) - - def set_value(self, value): - self.validate_value(value) - self.input_field.set_value(value) - - def _on_value_change(self, *args, **kwargs): - self._is_invalid = self.input_field.has_invalid_value() - return super(RawJsonWidget, self)._on_value_change(*args, **kwargs) - - def item_value(self): - if self.is_invalid: - return NOT_SET - - value = self.input_field.json_value() - if not self.is_environ: - return value - - output = {} - for key, value in value.items(): - output[key.upper()] = value - return output - - def config_value(self): - value = self.item_value() - if self.is_environ: - if METADATA_KEY not in value: - value[METADATA_KEY] = {} - - env_keys = [] - for key in value.keys(): - if key is not METADATA_KEY: - env_keys.append(key) - - value[METADATA_KEY]["environments"] = { - self.env_group_key: env_keys - } - return {self.key: value} - - -class ListItem(QtWidgets.QWidget, SettingObject): - _btn_size = 20 - value_changed = QtCore.Signal(object) - - def __init__( - self, item_schema, config_parent, parent, is_strict=False - ): - super(ListItem, self).__init__(parent) - - self._set_default_attributes() - - self._is_strict = is_strict - - self._parent = config_parent - self._any_parent_is_group = True - self._is_empty = False - - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(3) - - char_up = qtawesome.charmap("fa.angle-up") - char_down = qtawesome.charmap("fa.angle-down") - - if not self._is_strict: - self.add_btn = QtWidgets.QPushButton("+") - self.remove_btn = QtWidgets.QPushButton("-") - self.up_btn = QtWidgets.QPushButton(char_up) - self.down_btn = QtWidgets.QPushButton(char_down) - - font_up_down = qtawesome.font("fa", 13) - self.up_btn.setFont(font_up_down) - self.down_btn.setFont(font_up_down) - - self.add_btn.setFocusPolicy(QtCore.Qt.ClickFocus) - self.remove_btn.setFocusPolicy(QtCore.Qt.ClickFocus) - self.up_btn.setFocusPolicy(QtCore.Qt.ClickFocus) - self.down_btn.setFocusPolicy(QtCore.Qt.ClickFocus) - - self.add_btn.setFixedSize(self._btn_size, self._btn_size) - self.remove_btn.setFixedSize(self._btn_size, self._btn_size) - self.up_btn.setFixedSize(self._btn_size, self._btn_size) - self.down_btn.setFixedSize(self._btn_size, self._btn_size) - - self.add_btn.setProperty("btn-type", "tool-item") - self.remove_btn.setProperty("btn-type", "tool-item") - self.up_btn.setProperty("btn-type", "tool-item") - self.down_btn.setProperty("btn-type", "tool-item") - - self.add_btn.clicked.connect(self._on_add_clicked) - self.remove_btn.clicked.connect(self._on_remove_clicked) - self.up_btn.clicked.connect(self._on_up_clicked) - self.down_btn.clicked.connect(self._on_down_clicked) - - layout.addWidget(self.add_btn, 0) - layout.addWidget(self.remove_btn, 0) - - ItemKlass = TypeToKlass.types[item_schema["type"]] - self.value_input = ItemKlass( - item_schema, - self, - as_widget=True - ) - self.value_input.create_ui() - - layout.addWidget(self.value_input, 1) - - if not self._is_strict: - self.spacer_widget = QtWidgets.QWidget(self) - self.spacer_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground) - self.spacer_widget.setVisible(False) - - layout.addWidget(self.spacer_widget, 1) - - layout.addWidget(self.up_btn, 0) - layout.addWidget(self.down_btn, 0) - - self.value_input.value_changed.connect(self._on_value_change) - - @property - def as_widget(self): - return self._parent.as_widget - - @property - def any_parent_as_widget(self): - return self.as_widget or self._parent.any_parent_as_widget - - def set_as_empty(self, is_empty=True): - self._is_empty = is_empty - - self.spacer_widget.setVisible(is_empty) - self.value_input.setVisible(not is_empty) - self.remove_btn.setEnabled(not is_empty) - self.up_btn.setVisible(not is_empty) - self.down_btn.setVisible(not is_empty) - self.order_changed() - self._on_value_change() - - def order_changed(self): - row = self.row() - parent_row_count = self.parent_rows_count() - if parent_row_count == 1: - self.up_btn.setVisible(False) - self.down_btn.setVisible(False) - return - - if not self.up_btn.isVisible(): - self.up_btn.setVisible(True) - self.down_btn.setVisible(True) - - if row == 0: - self.up_btn.setEnabled(False) - self.down_btn.setEnabled(True) - - elif row == parent_row_count - 1: - self.up_btn.setEnabled(True) - self.down_btn.setEnabled(False) - - else: - self.up_btn.setEnabled(True) - self.down_btn.setEnabled(True) - - def _on_value_change(self, item=None): - self.value_changed.emit(self) - - def row(self): - return self._parent.input_fields.index(self) - - def parent_rows_count(self): - return len(self._parent.input_fields) - - def _on_add_clicked(self): - if self._is_empty: - self.set_as_empty(False) - else: - self._parent.add_row(row=self.row() + 1) - - def _on_remove_clicked(self): - self._parent.remove_row(self) - - def _on_up_clicked(self): - row = self.row() - self._parent.swap_rows(row - 1, row) - - def _on_down_clicked(self): - row = self.row() - self._parent.swap_rows(row, row + 1) - - def config_value(self): - if not self._is_empty: - return self.value_input.item_value() - return NOT_SET - - @property - def is_modified(self): - if self._is_empty: - return False - return self.value_input.is_modified - - @property - def child_has_studio_override(self): - return self.value_input.child_has_studio_override - - @property - def child_modified(self): - return self.value_input.child_modified - - @property - def child_overriden(self): - return self.value_input.child_overriden - - def hierarchical_style_update(self): - self.value_input.hierarchical_style_update() - - def mouseReleaseEvent(self, event): - return QtWidgets.QWidget.mouseReleaseEvent(self, event) - - def update_default_values(self, value): - self.value_input.update_default_values(value) - - def update_studio_values(self, value): - self.value_input.update_studio_values(value) - - def apply_overrides(self, value): - self.value_input.apply_overrides(value) - - -class ListWidget(QtWidgets.QWidget, InputObject): - default_input_value = [] - value_changed = QtCore.Signal(object) - valid_value_types = (list, ) - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(ListWidget, self).__init__(parent_widget) - self.setObjectName("ListWidget") - - self.initial_attributes(schema_data, parent, as_widget) - - self.use_label_wrap = schema_data.get("use_label_wrap") or False - # Used only if `use_label_wrap` is set to True - self.collapsible = schema_data.get("collapsible") or True - self.collapsed = schema_data.get("collapsed") or False - - self.expand_in_grid = bool(self.use_label_wrap) - - if self.as_widget and self.use_label_wrap: - raise ValueError( - "`ListWidget` can't have set `use_label_wrap` to True and" - " be used as widget at the same time." - ) - - if self.use_label_wrap and not self.label: - raise ValueError( - "`ListWidget` can't have set `use_label_wrap` to True and" - " not have set \"label\" key at the same time." - ) - - self.input_fields = [] - - object_type = schema_data["object_type"] - if isinstance(object_type, dict): - self.item_schema = object_type - else: - self.item_schema = { - "type": object_type - } - - def create_ui(self, label_widget=None): - main_layout = QtWidgets.QHBoxLayout(self) - main_layout.setContentsMargins(0, 0, 0, 0) - main_layout.setSpacing(0) - - body_widget = None - if self.as_widget: - pass - - elif self.use_label_wrap: - body_widget = ExpandingWidget(self.label, self) - main_layout.addWidget(body_widget) - - label_widget = body_widget.label_widget - - elif not label_widget: - if self.label: - label_widget = QtWidgets.QLabel(self.label, self) - main_layout.addWidget( - label_widget, alignment=QtCore.Qt.AlignTop - ) - - self.label_widget = label_widget - - self.body_widget = body_widget - - if body_widget is None: - content_parent_widget = self - else: - content_parent_widget = body_widget - - content_state = "" - - inputs_widget = QtWidgets.QWidget(content_parent_widget) - inputs_widget.setObjectName("ContentWidget") - inputs_widget.setProperty("content_state", content_state) - inputs_layout = QtWidgets.QVBoxLayout(inputs_widget) - inputs_layout.setContentsMargins(CHILD_OFFSET, 5, 0, 5) - - if body_widget is None: - main_layout.addWidget(inputs_widget) - else: - body_widget.set_content_widget(inputs_widget) - - self.body_widget = body_widget - self.inputs_widget = inputs_widget - self.inputs_layout = inputs_layout - - if body_widget: - if not self.collapsible: - body_widget.hide_toolbox(hide_content=False) - - elif self.collapsed: - body_widget.toggle_content() - - self.setAttribute(QtCore.Qt.WA_TranslucentBackground) - - self.add_row(is_empty=True) - - def count(self): - return len(self.input_fields) - - def update_studio_values(self, parent_values): - super(ListWidget, self).update_studio_values(parent_values) - - self.hierarchical_style_update() - - def set_value(self, value): - self.validate_value(value) - - previous_inputs = tuple(self.input_fields) - for item_value in value: - self.add_row(value=item_value) - - for input_field in previous_inputs: - self.remove_row(input_field) - - if self.count() == 0: - self.add_row(is_empty=True) - - def swap_rows(self, row_1, row_2): - if row_1 == row_2: - return - - if row_1 > row_2: - row_1, row_2 = row_2, row_1 - - field_1 = self.input_fields[row_1] - field_2 = self.input_fields[row_2] - - self.input_fields[row_1] = field_2 - self.input_fields[row_2] = field_1 - - layout_index = self.inputs_layout.indexOf(field_1) - self.inputs_layout.insertWidget(layout_index + 1, field_1) - - field_1.order_changed() - field_2.order_changed() - - def add_row(self, row=None, value=None, is_empty=False): - # Create new item - item_widget = ListItem(self.item_schema, self, self.inputs_widget) - - previous_field = None - next_field = None - - if row is None: - if self.input_fields: - previous_field = self.input_fields[-1] - self.inputs_layout.addWidget(item_widget) - self.input_fields.append(item_widget) - else: - if row > 0: - previous_field = self.input_fields[row - 1] - - max_index = self.count() - if row < max_index: - next_field = self.input_fields[row] - - self.inputs_layout.insertWidget(row, item_widget) - self.input_fields.insert(row, item_widget) - - if previous_field: - previous_field.order_changed() - - if next_field: - next_field.order_changed() - - if is_empty: - item_widget.set_as_empty() - item_widget.value_changed.connect(self._on_value_change) - - item_widget.order_changed() - - previous_input = None - for input_field in self.input_fields: - if previous_input is not None: - self.setTabOrder( - previous_input, input_field.value_input.focusProxy() - ) - previous_input = input_field.value_input.focusProxy() - - # Set text if entered text is not None - # else (when add button clicked) trigger `_on_value_change` - if value is not None: - if self._is_overriden: - item_widget.apply_overrides(value) - elif not self._has_studio_override: - item_widget.update_default_values(value) - else: - item_widget.update_studio_values(value) - self.hierarchical_style_update() - else: - self._on_value_change() - self.updateGeometry() - - def remove_row(self, item_widget): - item_widget.value_changed.disconnect() - - row = self.input_fields.index(item_widget) - previous_field = None - next_field = None - if row > 0: - previous_field = self.input_fields[row - 1] - - if row != len(self.input_fields) - 1: - next_field = self.input_fields[row + 1] - - self.inputs_layout.removeWidget(item_widget) - self.input_fields.pop(row) - item_widget.setParent(None) - item_widget.deleteLater() - - if previous_field: - previous_field.order_changed() - - if next_field: - next_field.order_changed() - - if self.count() == 0: - self.add_row(is_empty=True) - - self._on_value_change() - self.updateGeometry() - - def apply_overrides(self, parent_values): - self._is_modified = False - if self.as_widget: - override_value = parent_values - elif parent_values is NOT_SET or self.key not in parent_values: - override_value = NOT_SET - else: - override_value = parent_values[self.key] - - self.override_value = override_value - - if override_value is NOT_SET: - self._is_overriden = False - self._was_overriden = False - if self.has_studio_override: - value = self.studio_value - else: - value = self.default_value - else: - self._is_overriden = True - self._was_overriden = True - value = override_value - - self._is_modified = False - self._state = None - - self.set_value(value) - - def hierarchical_style_update(self): - for input_field in self.input_fields: - input_field.hierarchical_style_update() - self.update_style() - - @property - def is_modified(self): - is_modified = super(ListWidget, self).is_modified - if is_modified: - return is_modified - - for input_field in self.input_fields: - if input_field.is_modified: - return True - return False - - def update_style(self, is_overriden=None): - if not self.label_widget: - return - - child_invalid = self.child_invalid - if self.body_widget: - child_state = self.style_state( - self.child_has_studio_override, - child_invalid, - self.child_overriden, - self.child_modified - ) - if child_state: - child_state = "child-{}".format(child_state) - - if child_state != self._child_state: - self.body_widget.side_line_widget.setProperty( - "state", child_state - ) - self.body_widget.side_line_widget.style().polish( - self.body_widget.side_line_widget - ) - self._child_state = child_state - - state = self.style_state( - self.had_studio_override, - child_invalid, - self.is_overriden, - self.is_modified - ) - if self._state == state: - return - - self.label_widget.setProperty("state", state) - self.label_widget.style().polish(self.label_widget) - - self._state = state - - def item_value(self): - output = [] - for item in self.input_fields: - value = item.config_value() - if value is not NOT_SET: - output.append(value) - return output - - -class ListStrictWidget(QtWidgets.QWidget, InputObject): - value_changed = QtCore.Signal(object) - _default_input_value = None - valid_value_types = (list, ) - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(ListStrictWidget, self).__init__(parent_widget) - self.setObjectName("ListStrictWidget") - - self.initial_attributes(schema_data, parent, as_widget) - - self.is_horizontal = schema_data.get("horizontal", True) - self.object_types = self.schema_data["object_types"] - - self.input_fields = [] - - def create_ui(self, label_widget=None): - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 5) - layout.setSpacing(5) - - if not self.as_widget and not label_widget: - label = self.schema_data.get("label") - if label: - label_widget = QtWidgets.QLabel(label, self) - layout.addWidget(label_widget, alignment=QtCore.Qt.AlignTop) - elif self._is_group: - raise KeyError(( - "Schema item must contain \"label\" if `is_group` is True" - " to be able visualize changes and show actions." - )) - - self.label_widget = label_widget - - self._add_children(layout) - - def _add_children(self, layout): - inputs_widget = QtWidgets.QWidget(self) - inputs_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground) - layout.addWidget(inputs_widget) - - if self.is_horizontal: - inputs_layout = QtWidgets.QHBoxLayout(inputs_widget) - else: - inputs_layout = QtWidgets.QGridLayout(inputs_widget) - - inputs_layout.setContentsMargins(0, 0, 0, 0) - inputs_layout.setSpacing(3) - - self.inputs_widget = inputs_widget - self.inputs_layout = inputs_layout - - children_item_mapping = [] - for child_configuration in self.object_types: - item_widget = ListItem( - child_configuration, self, self.inputs_widget, is_strict=True - ) - - self.input_fields.append(item_widget) - item_widget.value_changed.connect(self._on_value_change) - - label = child_configuration.get("label") - label_widget = None - if label: - label_widget = QtWidgets.QLabel(label, self) - - children_item_mapping.append((label_widget, item_widget)) - - if self.is_horizontal: - self._add_children_horizontally(children_item_mapping) - else: - self._add_children_vertically(children_item_mapping) - - self.updateGeometry() - - def _add_children_vertically(self, children_item_mapping): - any_has_label = False - for item_mapping in children_item_mapping: - if item_mapping[0]: - any_has_label = True - break - - row = self.inputs_layout.count() - if not any_has_label: - self.inputs_layout.setColumnStretch(1, 1) - for item_mapping in children_item_mapping: - item_widget = item_mapping[1] - self.inputs_layout.addWidget(item_widget, row, 0, 1, 1) - - spacer_widget = QtWidgets.QWidget(self.inputs_widget) - self.inputs_layout.addWidget(spacer_widget, row, 1, 1, 1) - row += 1 - - else: - self.inputs_layout.setColumnStretch(2, 1) - for label_widget, item_widget in children_item_mapping: - self.inputs_layout.addWidget( - label_widget, row, 0, 1, 1, - alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignTop - ) - self.inputs_layout.addWidget(item_widget, row, 1, 1, 1) - - spacer_widget = QtWidgets.QWidget(self.inputs_widget) - self.inputs_layout.addWidget(spacer_widget, row, 2, 1, 1) - row += 1 - - def _add_children_horizontally(self, children_item_mapping): - for label_widget, item_widget in children_item_mapping: - if label_widget: - self.inputs_layout.addWidget(label_widget, 0) - self.inputs_layout.addWidget(item_widget, 0) - - spacer_widget = QtWidgets.QWidget(self.inputs_widget) - self.inputs_layout.addWidget(spacer_widget, 1) - - @property - def default_input_value(self): - if self._default_input_value is None: - self.set_value(NOT_SET) - self._default_input_value = self.item_value() - return self._default_input_value - - def set_value(self, value): - if self._is_overriden: - method_name = "apply_overrides" - elif not self._has_studio_override: - method_name = "update_default_values" - else: - method_name = "update_studio_values" - - for idx, input_field in enumerate(self.input_fields): - if value is NOT_SET: - _value = value - else: - if idx > len(value) - 1: - _value = NOT_SET - else: - _value = value[idx] - _method = getattr(input_field, method_name) - _method(_value) - - def hierarchical_style_update(self): - for input_field in self.input_fields: - input_field.hierarchical_style_update() - self.update_style() - - def update_style(self): - if not self.label_widget: - return - - state = self._style_state() - - if self._state == state: - return - - self._state = state - self.label_widget.setProperty("state", state) - self.label_widget.style().polish(self.label_widget) - - def item_value(self): - output = [] - for item in self.input_fields: - output.append(item.config_value()) - return output - - -class ModifiableDictItem(QtWidgets.QWidget, SettingObject): - _btn_size = 20 - value_changed = QtCore.Signal(object) - - def __init__(self, item_schema, config_parent, parent): - super(ModifiableDictItem, self).__init__(parent) - - self._set_default_attributes() - self._parent = config_parent - - any_parent_as_widget = config_parent.as_widget - if not any_parent_as_widget: - any_parent_as_widget = config_parent.any_parent_as_widget - - self._any_parent_as_widget = any_parent_as_widget - self._any_parent_is_group = True - - self._is_empty = False - self._is_key_duplicated = False - - self._is_required = False - - self.origin_key = NOT_SET - self.origin_key_label = NOT_SET - - if self.collapsable_key: - layout = QtWidgets.QVBoxLayout(self) - else: - layout = QtWidgets.QHBoxLayout(self) - - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(3) - - ItemKlass = TypeToKlass.types[item_schema["type"]] - value_input = ItemKlass( - item_schema, - self, - as_widget=True - ) - value_input.create_ui() - - key_input = QtWidgets.QLineEdit(self) - key_input.setObjectName("DictKey") - - key_label_input = None - wrapper_widget = None - if self.collapsable_key: - key_label_input = QtWidgets.QLineEdit(self) - - wrapper_widget = ExpandingWidget("", self) - layout.addWidget(wrapper_widget) - - content_widget = QtWidgets.QWidget(wrapper_widget) - content_widget.setObjectName("ContentWidget") - content_layout = QtWidgets.QHBoxLayout(content_widget) - content_layout.setContentsMargins(CHILD_OFFSET, 5, 0, 0) - content_layout.setSpacing(5) - - wrapper_widget.set_content_widget(content_widget) - - content_layout.addWidget(value_input) - - def key_input_focused_out(event): - QtWidgets.QLineEdit.focusOutEvent(key_input, event) - self._on_focus_lose() - - def key_label_input_focused_out(event): - QtWidgets.QLineEdit.focusOutEvent(key_label_input, event) - self._on_focus_lose() - - key_input.focusOutEvent = key_input_focused_out - key_label_input.focusOutEvent = key_label_input_focused_out - - spacer_widget = None - add_btn = None - if not self.collapsable_key: - spacer_widget = QtWidgets.QWidget(self) - spacer_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground) - spacer_widget.setVisible(False) - - add_btn = QtWidgets.QPushButton("+") - add_btn.setFocusPolicy(QtCore.Qt.ClickFocus) - add_btn.setProperty("btn-type", "tool-item") - add_btn.setFixedSize(self._btn_size, self._btn_size) - - edit_btn = None - if self.collapsable_key: - edit_btn = IconButton( - "fa.edit", QtCore.Qt.lightGray, QtCore.Qt.white - ) - edit_btn.setFocusPolicy(QtCore.Qt.ClickFocus) - edit_btn.setProperty("btn-type", "tool-item-icon") - edit_btn.setFixedHeight(self._btn_size) - - remove_btn = QtWidgets.QPushButton("-") - remove_btn.setFocusPolicy(QtCore.Qt.ClickFocus) - remove_btn.setProperty("btn-type", "tool-item") - remove_btn.setFixedSize(self._btn_size, self._btn_size) - - key_input_label_widget = None - key_label_input_label_widget = None - if self.collapsable_key: - key_input_label_widget = QtWidgets.QLabel("Key:") - key_label_input_label_widget = QtWidgets.QLabel("Label:") - wrapper_widget.add_widget_before_label(edit_btn) - wrapper_widget.add_widget_after_label(key_input_label_widget) - wrapper_widget.add_widget_after_label(key_input) - wrapper_widget.add_widget_after_label(key_label_input_label_widget) - wrapper_widget.add_widget_after_label(key_label_input) - wrapper_widget.add_widget_after_label(remove_btn) - - else: - layout.addWidget(add_btn, 0) - layout.addWidget(remove_btn, 0) - layout.addWidget(key_input, 0) - layout.addWidget(spacer_widget, 1) - layout.addWidget(value_input, 1) - - self.setFocusProxy(value_input) - - key_input.textChanged.connect(self._on_key_change) - key_input.returnPressed.connect(self._on_enter_press) - if key_label_input: - key_label_input.textChanged.connect(self._on_key_change) - key_label_input.returnPressed.connect(self._on_enter_press) - - value_input.value_changed.connect(self._on_value_change) - if add_btn: - add_btn.clicked.connect(self.on_add_clicked) - if edit_btn: - edit_btn.clicked.connect(self.on_edit_pressed) - remove_btn.clicked.connect(self.on_remove_clicked) - - self.key_input = key_input - self.key_input_label_widget = key_input_label_widget - self.key_label_input = key_label_input - self.key_label_input_label_widget = key_label_input_label_widget - self.value_input = value_input - self.wrapper_widget = wrapper_widget - - self.spacer_widget = spacer_widget - - self.add_btn = add_btn - self.edit_btn = edit_btn - self.remove_btn = remove_btn - - self.set_as_empty(self._is_empty) - - def _style_state(self): - if self.as_widget: - state = self.style_state( - False, - self._is_invalid, - False, - self.is_modified - ) - else: - state = self.style_state( - self.has_studio_override, - self.is_invalid, - self.is_overriden, - self.is_modified - ) - return state - - @property - def collapsable_key(self): - return self._parent.collapsable_key - - def key_value(self): - return self.key_input.text() - - def is_key_invalid(self): - if self._is_empty: - return False - - if self.key_value() == "": - return True - - if self._is_key_duplicated: - return True - return False - - def set_key_is_duplicated(self, duplicated): - if duplicated == self._is_key_duplicated: - return - - self._is_key_duplicated = duplicated - if self.collapsable_key: - if duplicated: - self.set_edit_mode(True) - else: - self._on_focus_lose() - self.update_style() - - def set_as_required(self, key): - self.key_input.setText(key) - self.key_input.setEnabled(False) - self._is_required = True - - if self._is_empty: - self.set_as_empty(False) - - if self.collapsable_key: - self.remove_btn.setVisible(False) - else: - self.remove_btn.setEnabled(False) - self.add_btn.setEnabled(False) - - def set_as_last_required(self): - if self.add_btn: - self.add_btn.setEnabled(True) - - def _on_focus_lose(self): - if ( - self.edit_btn.hasFocus() - or self.key_input.hasFocus() - or self.key_label_input.hasFocus() - or self.remove_btn.hasFocus() - ): - return - self._on_enter_press() - - def _on_enter_press(self): - if not self.collapsable_key: - return - - if self._is_empty: - self.on_add_clicked() - else: - self.set_edit_mode(False) - - def _on_key_label_change(self): - self.update_key_label() - - def _on_key_change(self): - if self.value_is_env_group: - self.value_input.env_group_key = self.key_input.text() - - self.update_key_label() - - self._on_value_change() - - def _on_value_change(self, item=None): - self.update_style() - self.value_changed.emit(self) - - def update_default_values(self, key, label, value): - self.origin_key = key - self.key_input.setText(key) - if self.key_label_input: - label = label or "" - self.origin_key_label = label - self.key_label_input.setText(label) - self.value_input.update_default_values(value) - - def update_studio_values(self, key, label, value): - self.origin_key = key - self.key_input.setText(key) - if self.key_label_input: - label = label or "" - self.origin_key_label = label - self.key_label_input.setText(label) - self.value_input.update_studio_values(value) - - def apply_overrides(self, key, label, value): - self.origin_key = key - self.key_input.setText(key) - if self.key_label_input: - label = label or "" - self.origin_key_label = label - self.key_label_input.setText(label) - self.value_input.apply_overrides(value) - - @property - def value_is_env_group(self): - return self._parent.value_is_env_group - - @property - def is_group(self): - return self._parent.is_group - - def update_key_label(self): - if not self.wrapper_widget: - return - key_value = self.key_input.text() - key_label_value = self.key_label_input.text() - if key_label_value: - label = "{} ({})".format(key_label_value, key_value) - else: - label = key_value - self.wrapper_widget.label_widget.setText(label) - - def on_add_clicked(self): - if not self.collapsable_key: - if self._is_empty: - self.set_as_empty(False) - else: - self._parent.add_row(row=self.row() + 1) - return - - if not self._is_empty: - return - - if not self.key_value(): - return - - self.set_as_empty(False) - self._parent.add_row(row=self.row() + 1, is_empty=True) - - def on_edit_pressed(self): - if not self.key_input.isVisible(): - self.set_edit_mode() - else: - self.key_input.setFocus() - - def set_edit_mode(self, enabled=True): - if self.is_invalid and not enabled: - return - self.wrapper_widget.label_widget.setVisible(not enabled) - self.key_label_input_label_widget.setVisible(enabled) - self.key_input.setVisible(enabled) - self.key_input_label_widget.setVisible(enabled) - self.key_label_input.setVisible(enabled) - if not self._is_required: - self.remove_btn.setVisible(enabled) - if enabled: - if self.key_input.isEnabled(): - self.key_input.setFocus() - else: - self.key_label_input.setFocus() - - def on_remove_clicked(self): - self._parent.remove_row(self) - - def set_as_empty(self, is_empty=True): - self._is_empty = is_empty - - self.value_input.setVisible(not is_empty) - if not self.collapsable_key: - self.key_input.setVisible(not is_empty) - self.remove_btn.setEnabled(not is_empty) - self.spacer_widget.setVisible(is_empty) - - else: - self.remove_btn.setVisible(False) - self.key_input_label_widget.setVisible(is_empty) - self.key_input.setVisible(is_empty) - self.key_label_input_label_widget.setVisible(is_empty) - self.key_label_input.setVisible(is_empty) - self.edit_btn.setVisible(not is_empty) - - self.wrapper_widget.label_widget.setVisible(not is_empty) - if is_empty: - self.wrapper_widget.hide_toolbox() - else: - self.wrapper_widget.show_toolbox() - self._on_value_change() - - @property - def any_parent_is_group(self): - return self._parent.any_parent_is_group - - def is_key_modified(self): - return self.key_value() != self.origin_key - - def is_key_label_modified(self): - return self.key_label_value() != self.origin_key_label - - def is_value_modified(self): - return self.value_input.is_modified - - @property - def is_modified(self): - if self._is_empty: - return False - return ( - self.is_key_modified() - or self.is_key_label_modified() - or self.is_value_modified() - ) - - def hierarchical_style_update(self): - self.value_input.hierarchical_style_update() - self.update_style() - - @property - def is_invalid(self): - if self._is_empty: - return False - return self.is_key_invalid() or self.value_input.is_invalid - - def update_style(self): - key_input_state = "" - if not self._is_empty: - if self.is_key_invalid(): - key_input_state = "invalid" - elif self.is_key_modified(): - key_input_state = "modified" - - self.key_input.setProperty("state", key_input_state) - self.key_input.style().polish(self.key_input) - - if not self.wrapper_widget: - return - - state = self._style_state() - - if self._state == state: - return - - self._state = state - - if self.wrapper_widget.label_widget: - self.wrapper_widget.label_widget.setProperty("state", state) - self.wrapper_widget.label_widget.style().polish( - self.wrapper_widget.label_widget - ) - - if state: - child_state = "child-{}".format(state) - else: - child_state = "" - - self.wrapper_widget.side_line_widget.setProperty("state", child_state) - self.wrapper_widget.side_line_widget.style().polish( - self.wrapper_widget.side_line_widget - ) - - def row(self): - return self._parent.input_fields.index(self) - - def key_label_value(self): - if self.collapsable_key: - return self.key_label_input.text() - return NOT_SET - - def item_value(self): - key = self.key_input.text() - value = self.value_input.item_value() - return {key: value} - - def config_value(self): - if self._is_empty: - return {} - return self.item_value() - - def mouseReleaseEvent(self, event): - return QtWidgets.QWidget.mouseReleaseEvent(self, event) - - -class ModifiableDict(QtWidgets.QWidget, InputObject): - default_input_value = {} - # Should be used only for dictionary with one datatype as value - # TODO this is actually input field (do not care if is group or not) - value_changed = QtCore.Signal(object) - expand_in_grid = True - valid_value_types = (dict, ) - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(ModifiableDict, self).__init__(parent_widget) - self.setObjectName("ModifiableDict") - - self.initial_attributes(schema_data, parent, as_widget) - - self.input_fields = [] - self.required_inputs_by_key = {} - - # Validation of "key" key - self.key = schema_data["key"] - self.value_is_env_group = ( - schema_data.get("value_is_env_group") or False - ) - self.hightlight_content = schema_data.get("highlight_content") or False - self.collapsable_key = schema_data.get("collapsable_key") or False - self.required_keys = schema_data.get("required_keys") or [] - - object_type = schema_data["object_type"] - if isinstance(object_type, dict): - self.item_schema = object_type - else: - # Backwards compatibility - self.item_schema = { - "type": object_type - } - input_modifiers = schema_data.get("input_modifiers") or {} - if input_modifiers: - self.log.warning(( - "Used deprecated key `input_modifiers` to define item." - " Rather use `object_type` as dictionary with modifiers." - )) - self.item_schema.update(input_modifiers) - - if self.value_is_env_group: - self.item_schema["env_group_key"] = "" - - def create_ui(self, label_widget=None): - if self.hightlight_content: - content_state = "hightlighted" - bottom_margin = 5 - else: - content_state = "" - bottom_margin = 0 - - main_layout = QtWidgets.QHBoxLayout(self) - main_layout.setContentsMargins(0, 0, 0, 0) - main_layout.setSpacing(0) - - label = self.schema_data.get("label") - - if self.as_widget: - body_widget = None - self.label_widget = label_widget - - elif label is None: - body_widget = None - self.label_widget = None - else: - body_widget = ExpandingWidget(self.schema_data["label"], self) - main_layout.addWidget(body_widget) - - self.label_widget = body_widget.label_widget - - self.body_widget = body_widget - - if body_widget is None: - content_parent_widget = self - else: - content_parent_widget = body_widget - - content_widget = QtWidgets.QWidget(content_parent_widget) - content_widget.setObjectName("ContentWidget") - content_widget.setProperty("content_state", content_state) - content_layout = QtWidgets.QVBoxLayout(content_widget) - content_layout.setContentsMargins(CHILD_OFFSET, 5, 0, bottom_margin) - - if body_widget is None: - main_layout.addWidget(content_widget) - else: - body_widget.set_content_widget(content_widget) - - self.body_widget = body_widget - self.content_widget = content_widget - self.content_layout = content_layout - - if body_widget: - collapsable = self.schema_data.get("collapsable", True) - if collapsable: - collapsed = self.schema_data.get("collapsed", True) - if not collapsed: - body_widget.toggle_content() - - else: - body_widget.hide_toolbox(hide_content=False) - - self.setAttribute(QtCore.Qt.WA_TranslucentBackground) - - last_required_item = None - for key in self.required_keys: - last_required_item = self.add_row(key=key, is_required=True) - - if last_required_item: - last_required_item.set_as_last_required() - else: - self.add_row(is_empty=True) - - def count(self): - return len(self.input_fields) - - def set_value(self, value): - self.validate_value(value) - - metadata = value.get(METADATA_KEY, {}) - dynamic_key_labels = metadata.get("dynamic_key_label") or {} - - required_items = list(self.required_inputs_by_key.values()) - previous_inputs = list() - for input_field in self.input_fields: - if input_field not in required_items: - previous_inputs.append(input_field) - - for item_key, item_value in value.items(): - if item_key is METADATA_KEY: - continue - - label = dynamic_key_labels.get(item_key) - self.add_row(key=item_key, label=label, value=item_value) - - if self.collapsable_key: - self.add_row(is_empty=True) - - for input_field in previous_inputs: - self.remove_row(input_field) - - if self.count() == 0: - self.add_row(is_empty=True) - - def _on_value_change(self, item=None): - if self.ignore_value_changes: - return - - fields_by_keys = collections.defaultdict(list) - for input_field in self.input_fields: - key = input_field.key_value() - fields_by_keys[key].append(input_field) - - for fields in fields_by_keys.values(): - if len(fields) == 1: - field = fields[0] - field.set_key_is_duplicated(False) - else: - for field in fields: - field.set_key_is_duplicated(True) - - if self.is_overidable: - self._is_overriden = True - else: - self._has_studio_override = True - - if self._is_invalid: - self._is_modified = True - elif self._is_overriden: - self._is_modified = self.item_value() != self.override_value - elif self._has_studio_override: - self._is_modified = self.item_value() != self.studio_value - else: - self._is_modified = self.item_value() != self.default_value - - self.update_style() - - self.value_changed.emit(self) - - @property - def is_modified(self): - is_modified = super(ModifiableDict, self).is_modified - if is_modified: - return is_modified - - for input_field in self.input_fields: - if input_field.is_modified: - return True - return False - - def hierarchical_style_update(self): - for input_field in self.input_fields: - input_field.hierarchical_style_update() - self.update_style() - - def update_style(self): - state = self._style_state() - - if self._state == state: - return - - self._state = state - - if self.label_widget: - self.label_widget.setProperty("state", state) - self.label_widget.style().polish(self.label_widget) - - if not self.body_widget: - return - - if state: - child_state = "child-{}".format(state) - else: - child_state = "" - - self.body_widget.side_line_widget.setProperty("state", child_state) - self.body_widget.side_line_widget.style().polish( - self.body_widget.side_line_widget - ) - - def all_item_values(self): - output = {} - for item in self.input_fields: - output.update(item.item_value()) - return output - - def item_value_with_metadata(self): - if not self.collapsable_key: - output = self.item_value() - - else: - output = {} - labels_by_key = {} - for item in self.input_fields: - labels_by_key[item.key_value()] = item.key_label_value() - output.update(item.config_value()) - if METADATA_KEY not in output: - output[METADATA_KEY] = {} - output[METADATA_KEY]["dynamic_key_label"] = labels_by_key - - if self.value_is_env_group: - for env_group_key, value in tuple(output.items()): - env_keys = [] - for key in value.keys(): - if key is not METADATA_KEY: - env_keys.append(key) - - if METADATA_KEY not in value: - value[METADATA_KEY] = {} - - value[METADATA_KEY]["environments"] = {env_group_key: env_keys} - output[env_group_key] = value - return output - - def item_value(self): - output = {} - for item in self.input_fields: - output.update(item.config_value()) - return output - - def config_value(self): - return {self.key: self.item_value_with_metadata()} - - def _create_item(self, row, key, is_empty, is_required): - # Create new item - item_widget = ModifiableDictItem( - self.item_schema, self, self.content_widget - ) - if is_empty: - item_widget.set_as_empty() - - if is_required: - item_widget.set_as_required(key) - self.required_inputs_by_key[key] = item_widget - - item_widget.value_changed.connect(self._on_value_change) - - if row is None: - self.content_layout.addWidget(item_widget) - self.input_fields.append(item_widget) - else: - self.content_layout.insertWidget(row, item_widget) - self.input_fields.insert(row, item_widget) - - previous_input = None - if self.collapsable_key: - for input_field in self.input_fields: - if previous_input is not None: - self.setTabOrder( - previous_input, input_field.value_input - ) - previous_input = input_field.value_input.focusProxy() - - else: - for input_field in self.input_fields: - if previous_input is not None: - self.setTabOrder( - previous_input, input_field.key_input - ) - previous_input = input_field.value_input.focusProxy() - self.setTabOrder( - input_field.key_input, previous_input - ) - return item_widget - - def add_row( - self, - row=None, - key=None, - label=None, - value=None, - is_empty=False, - is_required=False - ): - item_widget = self.required_inputs_by_key.get(key) - if not item_widget: - item_widget = self._create_item(row, key, is_empty, is_required) - - # Set value if entered value is not None - # else (when add button clicked) trigger `_on_value_change` - if value is not None and key is not None: - if not self._has_studio_override: - item_widget.update_default_values(key, label, value) - elif self._is_overriden: - item_widget.apply_overrides(key, label, value) - else: - item_widget.update_studio_values(key, label, value) - self.hierarchical_style_update() - else: - self._on_value_change() - self.parent().updateGeometry() - - return item_widget - - def remove_row(self, item_widget): - item_widget.value_changed.disconnect() - - self.content_layout.removeWidget(item_widget) - self.input_fields.remove(item_widget) - item_widget.setParent(None) - item_widget.deleteLater() - - if self.count() == 0: - self.add_row(is_empty=True) - - self._on_value_change() - self.parent().updateGeometry() - - @property - def is_invalid(self): - return self._is_invalid or self.child_invalid - - @property - def child_invalid(self): - for input_field in self.input_fields: - if input_field.is_invalid: - return True - return False - - -# Dictionaries -class DictWidget(QtWidgets.QWidget, SettingObject): - value_changed = QtCore.Signal(object) - expand_in_grid = True - valid_value_types = (dict, type(NOT_SET)) - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(DictWidget, self).__init__(parent_widget) - - self.initial_attributes(schema_data, parent, as_widget) - - self.input_fields = [] - - self.checkbox_widget = None - self.checkbox_key = schema_data.get("checkbox_key") - - self.highlight_content = schema_data.get("highlight_content", False) - self.show_borders = schema_data.get("show_borders", True) - self.collapsable = schema_data.get("collapsable", True) - self.collapsed = schema_data.get("collapsed", True) - - def create_ui(self, label_widget=None): - if not self.as_widget and self.schema_data.get("label") is None: - self._ui_item_without_label() - else: - self._ui_item_or_as_widget(label_widget) - - for child_data in self.schema_data.get("children", []): - self.add_children_gui(child_data) - - any_visible = False - for input_field in self.input_fields: - if not input_field.hidden_by_role: - any_visible = True - break - - if not any_visible: - self.hide() - - def _ui_item_without_label(self): - if self._is_group: - raise TypeError( - "Dictionary without label can't be marked as group input." - ) - - self.setObjectName("DictInvisible") - - self.label_widget = None - self.body_widget = None - self.content_layout = QtWidgets.QGridLayout(self) - self.content_layout.setContentsMargins(0, 0, 0, 0) - self.content_layout.setSpacing(5) - - def _ui_item_or_as_widget(self, label_widget): - content_widget = QtWidgets.QWidget(self) - - if self.as_widget: - content_widget.setObjectName("DictAsWidgetBody") - show_borders = str(int(self.show_borders)) - content_widget.setProperty("show_borders", show_borders) - content_layout_margins = (5, 5, 5, 5) - main_layout_spacing = 5 - body_widget = None - - else: - content_widget.setObjectName("ContentWidget") - if self.highlight_content: - content_state = "hightlighted" - bottom_margin = 5 - else: - content_state = "" - bottom_margin = 0 - content_widget.setProperty("content_state", content_state) - content_layout_margins = (CHILD_OFFSET, 5, 0, bottom_margin) - main_layout_spacing = 0 - - body_widget = ExpandingWidget(self.schema_data["label"], self) - label_widget = body_widget.label_widget - body_widget.set_content_widget(content_widget) - - content_layout = QtWidgets.QGridLayout(content_widget) - content_layout.setContentsMargins(*content_layout_margins) - - main_layout = QtWidgets.QHBoxLayout(self) - main_layout.setContentsMargins(0, 0, 0, 0) - main_layout.setSpacing(main_layout_spacing) - if not body_widget: - main_layout.addWidget(content_widget) - else: - main_layout.addWidget(body_widget) - - self.label_widget = label_widget - self.body_widget = body_widget - self.content_layout = content_layout - - if body_widget: - if len(self.input_fields) == 1 and self.checkbox_widget: - body_widget.hide_toolbox(hide_content=True) - - elif self.collapsable: - if not self.collapsed: - body_widget.toggle_content() - else: - body_widget.hide_toolbox(hide_content=False) - - def add_children_gui(self, child_configuration): - item_type = child_configuration["type"] - klass = TypeToKlass.types.get(item_type) - - row = self.content_layout.rowCount() - if not getattr(klass, "is_input_type", False): - item = klass(child_configuration, self) - self.content_layout.addWidget(item, row, 0, 1, 2) - return item - - if self.checkbox_key and not self.checkbox_widget: - key = child_configuration.get("key") - if key == self.checkbox_key: - if child_configuration["type"] != "boolean": - self.log.warning(( - "SCHEMA BUG: Dictionary item has set as checkbox" - " item invalid type \"{}\". Expected \"boolean\"." - ).format(child_configuration["type"])) - elif self.body_widget is None: - self.log.warning(( - "SCHEMA BUG: Dictionary item has set checkbox" - " item but item does not have label." - ).format(child_configuration["type"])) - else: - return self._add_checkbox_child(child_configuration) - - label_widget = None - item = klass(child_configuration, self) - if not item.expand_in_grid: - label = child_configuration.get("label") - if label is not None: - label_widget = GridLabelWidget(label, self) - self.content_layout.addWidget(label_widget, row, 0, 1, 1) - - item.create_ui(label_widget=label_widget) - item.value_changed.connect(self._on_value_change) - - if label_widget: - if item.hidden_by_role: - label_widget.hide() - label_widget.input_field = item - self.content_layout.addWidget(item, row, 1, 1, 1) - else: - self.content_layout.addWidget(item, row, 0, 1, 2) - - self.input_fields.append(item) - return item - - def _add_checkbox_child(self, child_configuration): - item = BooleanWidget( - child_configuration, self - ) - item.create_ui(label_widget=self.label_widget) - item.value_changed.connect(self._on_value_change) - - self.body_widget.add_widget_before_label(item) - self.checkbox_widget = item - self.input_fields.append(item) - return item - - def remove_overrides(self): - self._is_overriden = False - self._is_modified = False - for input_field in self.input_fields: - input_field.remove_overrides() - - def reset_to_pype_default(self): - for input_field in self.input_fields: - input_field.reset_to_pype_default() - self._has_studio_override = False - - def set_studio_default(self): - for input_field in self.input_fields: - input_field.set_studio_default() - - if self.is_group: - self._has_studio_override = True - - def discard_changes(self): - self._is_modified = False - self._is_overriden = self._was_overriden - self._has_studio_override = self._had_studio_override - - for input_field in self.input_fields: - input_field.discard_changes() - - self._is_modified = self.child_modified - if not self.is_overidable and self.as_widget: - if self.has_studio_override: - self._is_modified = self.studio_value != self.item_value() - else: - self._is_modified = self.default_value != self.item_value() - - self._state = None - self._is_overriden = self._was_overriden - - def set_as_overriden(self): - if self.is_overriden: - return - - if self.is_group: - self._is_overriden = True - return - - for item in self.input_fields: - item.set_as_overriden() - - def update_default_values(self, parent_values): - # Make sure this is set to False - self._state = None - self._child_state = None - - value = NOT_SET - if self.as_widget: - value = parent_values - elif parent_values is not NOT_SET: - value = parent_values.get(self.key, NOT_SET) - - try: - self.validate_value(value) - except InvalidValueType as exc: - value = NOT_SET - self.log.warning(exc.msg) - - for item in self.input_fields: - item.update_default_values(value) - - def update_studio_values(self, parent_values): - # Make sure this is set to False - self._state = None - self._child_state = None - value = NOT_SET - if self.as_widget: - value = parent_values - else: - if parent_values is not NOT_SET: - value = parent_values.get(self.key, NOT_SET) - - self._has_studio_override = False - if self.is_group and value is not NOT_SET: - self._has_studio_override = True - - self._had_studio_override = bool(self._has_studio_override) - - try: - self.validate_value(value) - except InvalidValueType as exc: - value = NOT_SET - self._has_studio_override = False - self._had_studio_override = False - self.log.warning(exc.msg) - - for item in self.input_fields: - item.update_studio_values(value) - - def apply_overrides(self, parent_values): - # Make sure this is set to False - self._state = None - self._child_state = None - - if self.as_widget: - override_values = parent_values - else: - metadata = {} - groups = tuple() - override_values = NOT_SET - if parent_values is not NOT_SET: - metadata = parent_values.get(METADATA_KEY) or metadata - groups = metadata.get("groups") or groups - override_values = parent_values.get(self.key, override_values) - - self._is_overriden = self.key in groups - - try: - self.validate_value(override_values) - except InvalidValueType as exc: - override_values = NOT_SET - self.log.warning(exc.msg) - - for item in self.input_fields: - item.apply_overrides(override_values) - - if not self.as_widget: - if not self._is_overriden: - self._is_overriden = ( - self.is_group - and self.is_overidable - and self.child_overriden - ) - self._was_overriden = bool(self._is_overriden) - - def _on_value_change(self, item=None): - if self.ignore_value_changes: - return - - if self.is_group and not (self.as_widget or self.any_parent_as_widget): - if self.is_overidable: - self._is_overriden = True - else: - self._has_studio_override = True - - # TODO check if this is required - self.hierarchical_style_update() - - self.value_changed.emit(self) - - self.update_style() - - def hierarchical_style_update(self): - for input_field in self.input_fields: - input_field.hierarchical_style_update() - self.update_style() - - def update_style(self, is_overriden=None): - # TODO add style update when used as widget - if not self.body_widget: - return - - child_has_studio_override = self.child_has_studio_override - child_modified = self.child_modified - child_invalid = self.child_invalid - child_state = self.style_state( - child_has_studio_override, - child_invalid, - self.child_overriden, - child_modified - ) - if child_state: - child_state = "child-{}".format(child_state) - - if child_state != self._child_state: - self.body_widget.side_line_widget.setProperty("state", child_state) - self.body_widget.side_line_widget.style().polish( - self.body_widget.side_line_widget - ) - self._child_state = child_state - - state = self.style_state( - self.had_studio_override, - child_invalid, - self.is_overriden, - self.is_modified - ) - if self._state == state: - return - - self.label_widget.setProperty("state", state) - self.label_widget.style().polish(self.label_widget) - - self._state = state - - @property - def is_modified(self): - if self.is_group: - return self._is_modified or self.child_modified - return False - - @property - def child_has_studio_override(self): - for input_field in self.input_fields: - if ( - input_field.has_studio_override - or input_field.child_has_studio_override - ): - return True - return False - - @property - def child_modified(self): - for input_field in self.input_fields: - if input_field.child_modified: - return True - return False - - @property - def child_overriden(self): - for input_field in self.input_fields: - if input_field.is_overriden or input_field.child_overriden: - return True - return False - - @property - def child_invalid(self): - for input_field in self.input_fields: - if input_field.child_invalid: - return True - return False - - def get_invalid(self): - output = [] - for input_field in self.input_fields: - output.extend(input_field.get_invalid()) - return output - - def item_value(self): - output = {} - for input_field in self.input_fields: - # TODO maybe merge instead of update should be used - # NOTE merge is custom function which merges 2 dicts - output.update(input_field.config_value()) - return output - - def _override_values(self, project_overrides): - values = {} - groups = [] - for input_field in self.input_fields: - if project_overrides: - value, is_group = input_field.overrides() - else: - value, is_group = input_field.studio_overrides() - if value is NOT_SET: - continue - - if METADATA_KEY in value and METADATA_KEY in values: - new_metadata = value.pop(METADATA_KEY) - values[METADATA_KEY] = self.merge_metadata( - values[METADATA_KEY], new_metadata - ) - - values.update(value) - if is_group: - groups.extend(value.keys()) - - if groups: - if METADATA_KEY not in values: - values[METADATA_KEY] = {} - values[METADATA_KEY]["groups"] = groups - return {self.key: values}, self.is_group - - def studio_overrides(self): - if ( - not (self.as_widget or self.any_parent_as_widget) - and not self.has_studio_override - and not self.child_has_studio_override - ): - return NOT_SET, False - return self._override_values(False) - - def overrides(self): - if not self.is_overriden and not self.child_overriden: - return NOT_SET, False - return self._override_values(True) - - -class PathWidget(QtWidgets.QWidget, SettingObject): - value_changed = QtCore.Signal(object) - platforms = ("windows", "darwin", "linux") - platform_labels_mapping = { - "windows": "Windows", - "darwin": "MacOS", - "linux": "Linux" - } - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(PathWidget, self).__init__(parent_widget) - - self.initial_attributes(schema_data, parent, as_widget) - - # This is partial input and dictionary input - if not self.any_parent_is_group and not self._as_widget: - self._is_group = True - else: - self._is_group = False - - self.multiplatform = schema_data.get("multiplatform", False) - self.multipath = schema_data.get("multipath", False) - self.with_arguments = schema_data.get("with_arguments", False) - - self.input_field = None - - def create_ui(self, label_widget=None): - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(5) - - if not self.as_widget and not label_widget: - label_widget = QtWidgets.QLabel(self.schema_data["label"]) - label_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground) - layout.addWidget(label_widget, 0, alignment=QtCore.Qt.AlignTop) - self.label_widget = label_widget - - self.content_widget = QtWidgets.QWidget(self) - self.content_layout = QtWidgets.QVBoxLayout(self.content_widget) - self.content_layout.setSpacing(0) - self.content_layout.setContentsMargins(0, 0, 0, 0) - - layout.addWidget(self.content_widget) - - self.create_ui_inputs() - - @property - def default_input_value(self): - if self.multipath: - value_type = list - else: - value_type = str - - if self.multiplatform: - return { - platform: value_type() - for platform in self.platforms - } - return value_type() - - def create_ui_inputs(self): - if not self.multiplatform and not self.multipath: - item_schema = { - "key": self.key, - "with_arguments": self.with_arguments - } - path_input = PathInputWidget(item_schema, self, as_widget=True) - path_input.create_ui(label_widget=self.label_widget) - - self.setFocusProxy(path_input) - self.content_layout.addWidget(path_input) - self.input_field = path_input - path_input.value_changed.connect(self._on_value_change) - return - - if not self.multiplatform: - item_schema = { - "key": self.key, - "object_type": { - "type": "path-input", - "with_arguments": self.with_arguments - } - } - input_widget = ListWidget(item_schema, self, as_widget=True) - input_widget.create_ui(label_widget=self.label_widget) - self.setFocusProxy(input_widget) - self.content_layout.addWidget(input_widget) - self.input_field = input_widget - input_widget.value_changed.connect(self._on_value_change) - return - - item_schema = { - "type": "dict", - "show_borders": False, - "children": [] - } - for platform_key in self.platforms: - platform_label = self.platform_labels_mapping[platform_key] - child_item = { - "key": platform_key, - "label": platform_label - } - if self.multipath: - child_item["type"] = "list" - child_item["object_type"] = { - "type": "path-input", - "with_arguments": self.with_arguments - } - else: - child_item["type"] = "path-input" - child_item["with_arguments"] = self.with_arguments - - item_schema["children"].append(child_item) - - input_widget = DictWidget(item_schema, self, as_widget=True) - input_widget.create_ui(label_widget=self.label_widget) - - self.content_layout.addWidget(input_widget) - self.input_field = input_widget - input_widget.value_changed.connect(self._on_value_change) - - def update_default_values(self, parent_values): - self._state = None - self._child_state = None - self._is_modified = False - - value = NOT_SET - if self.as_widget: - value = parent_values - elif parent_values is not NOT_SET: - value = parent_values.get(self.key, NOT_SET) - - if value is NOT_SET: - if self.available_for_role("developer"): - self.defaults_not_set = True - value = self.default_input_value - if value is NOT_SET: - raise NotImplementedError(( - "{} Does not have implemented" - " attribute `default_input_value`" - ).format(self)) - - else: - raise ValueError( - "Default value is not set. This is implementation BUG." - ) - else: - self.defaults_not_set = False - - self.default_value = value - self._has_studio_override = False - self._had_studio_override = False - - # TODO handle invalid value type - self.input_field.update_default_values(value) - - def update_studio_values(self, parent_values): - self._state = None - self._child_state = None - self._is_modified = False - - value = NOT_SET - if self.as_widget: - value = parent_values - elif parent_values is not NOT_SET: - value = parent_values.get(self.key, NOT_SET) - - self.studio_value = value - if value is not NOT_SET: - self._has_studio_override = True - self._had_studio_override = True - else: - self._has_studio_override = False - self._had_studio_override = False - - # TODO handle invalid value type - self.input_field.update_studio_values(value) - - def apply_overrides(self, parent_values): - self._is_modified = False - self._state = None - self._child_state = None - - override_values = NOT_SET - if self._as_widget: - override_values = parent_values - elif parent_values is not NOT_SET: - override_values = parent_values.get(self.key, NOT_SET) - - self._is_overriden = override_values is not NOT_SET - self._was_overriden = bool(self._is_overriden) - - # TODO handle invalid value type - self.input_field.update_studio_values(override_values) - - if not self._is_overriden: - self._is_overriden = ( - self.is_group - and self.is_overidable - and self.child_overriden - ) - self._is_modified = False - self._was_overriden = bool(self._is_overriden) - - def set_value(self, value): - if not self.multiplatform: - return self.input_field.set_value(value) - - for _input_field in self.input_field.input_fields: - _value = value.get(_input_field.key, NOT_SET) - if _value is NOT_SET: - continue - _input_field.set_value(_value) - - def _on_value_change(self, item=None): - if self.ignore_value_changes: - return - - if not self.any_parent_as_widget: - if self.is_overidable: - self._is_overriden = True - else: - self._has_studio_override = True - - if self._is_invalid: - self._is_modified = True - elif self._is_overriden: - self._is_modified = self.item_value() != self.override_value - elif self._has_studio_override: - self._is_modified = self.item_value() != self.studio_value - else: - self._is_modified = self.item_value() != self.default_value - - self.hierarchical_style_update() - - self.value_changed.emit(self) - - def update_style(self, is_overriden=None): - child_has_studio_override = self.child_has_studio_override - child_modified = self.child_modified - child_invalid = self.child_invalid - child_state = self.style_state( - child_has_studio_override, - child_invalid, - self.child_overriden, - child_modified - ) - if child_state: - child_state = "child-{}".format(child_state) - - if child_state != self._child_state: - self.setProperty("state", child_state) - self.style().polish(self) - self._child_state = child_state - - if self.label_widget: - state = self.style_state( - child_has_studio_override, - child_invalid, - self.is_overriden, - self.is_modified - ) - if self._state == state: - return - - self.label_widget.setProperty("state", state) - self.label_widget.style().polish(self.label_widget) - - self._state = state - - def remove_overrides(self): - self._is_overriden = False - self._is_modified = False - self.input_field.remove_overrides() - - def reset_to_pype_default(self): - self.input_field.reset_to_pype_default() - self._has_studio_override = False - - def set_studio_default(self): - self.input_field.set_studio_default() - - if self.is_group: - self._has_studio_override = True - - def discard_changes(self): - self._is_modified = False - self._is_overriden = self._was_overriden - self._has_studio_override = self._had_studio_override - - self.input_field.discard_changes() - - self._is_modified = self.child_modified - if not self.is_overidable and self.as_widget: - if self.has_studio_override: - self._is_modified = self.studio_value != self.item_value() - else: - self._is_modified = self.default_value != self.item_value() - - self._state = None - self._is_overriden = self._was_overriden - - def set_as_overriden(self): - self._is_overriden = True - - @property - def child_has_studio_override(self): - return self.has_studio_override - - @property - def child_modified(self): - return self.is_modified - - @property - def child_overriden(self): - return self.is_overriden - - @property - def child_invalid(self): - return self.input_field.child_invalid - - def hierarchical_style_update(self): - self.input_field.hierarchical_style_update() - self.update_style() - - def item_value(self): - return self.input_field.item_value() - - def studio_overrides(self): - if ( - not (self.as_widget or self.any_parent_as_widget) - and not self.has_studio_override - and not self.child_has_studio_override - ): - return NOT_SET, False - - value = {self.key: self.item_value()} - return value, self.is_group - - def overrides(self): - if not self.is_overriden and not self.child_overriden: - return NOT_SET, False - - value = {self.key: self.item_value()} - return value, self.is_group - - -class WrapperItemWidget(QtWidgets.QWidget, SettingObject): - value_changed = QtCore.Signal(object) - allow_actions = False - expand_in_grid = True - is_wrapper_item = True - - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(WrapperItemWidget, self).__init__(parent_widget) - - self.input_fields = [] - - self.initial_attributes(schema_data, parent, as_widget) - - if self.as_widget: - raise TypeError( - "Wrapper items ({}) can't be used as widgets.".format( - self.__class__.__name__ - ) - ) - - if self.is_group: - raise TypeError( - "Wrapper items ({}) can't be used as groups.".format( - self.__class__.__name__ - ) - ) - - self.setAttribute(QtCore.Qt.WA_TranslucentBackground) - - self.wrapper_initial_attributes(schema_data) - - def wrapper_initial_attributes(self, schema_data): - """Initialization of attributes for specific wrapper.""" - return - - def create_ui(self, label_widget=None): - """UI implementation.""" - raise NotImplementedError( - "Method `create_ui` not implemented." - ) - - def update_style(self): - """Update items styles.""" - return - - def apply_overrides(self, parent_values): - for item in self.input_fields: - item.apply_overrides(parent_values) - - def discard_changes(self): - self._is_modified = False - self._is_overriden = self._was_overriden - self._has_studio_override = self._had_studio_override - - for input_field in self.input_fields: - input_field.discard_changes() - - self._is_modified = self.child_modified - if not self.is_overidable and self.as_widget: - if self.has_studio_override: - self._is_modified = self.studio_value != self.item_value() - else: - self._is_modified = self.default_value != self.item_value() - - self._state = None - self._is_overriden = self._was_overriden - - def remove_overrides(self): - self._is_overriden = False - self._is_modified = False - for input_field in self.input_fields: - input_field.remove_overrides() - - def reset_to_pype_default(self): - for input_field in self.input_fields: - input_field.reset_to_pype_default() - self._has_studio_override = False - - def set_studio_default(self): - for input_field in self.input_fields: - input_field.set_studio_default() - - if self.is_group: - self._has_studio_override = True - - def set_as_overriden(self): - if self.is_overriden: - return - - if self.is_group: - self._is_overriden = True - return - - for item in self.input_fields: - item.set_as_overriden() - - def update_default_values(self, value): - for item in self.input_fields: - item.update_default_values(value) - - def update_studio_values(self, value): - for item in self.input_fields: - item.update_studio_values(value) - - def _on_value_change(self, item=None): - if self.ignore_value_changes: - return - - self.value_changed.emit(self) - if self.any_parent_is_group: - self.hierarchical_style_update() - self.update_style() - - @property - def child_has_studio_override(self): - for input_field in self.input_fields: - if ( - input_field.has_studio_override - or input_field.child_has_studio_override - ): - return True - return False - - @property - def child_modified(self): - for input_field in self.input_fields: - if input_field.child_modified: - return True - return False - - @property - def child_overriden(self): - for input_field in self.input_fields: - if input_field.is_overriden or input_field.child_overriden: - return True - return False - - @property - def child_invalid(self): - for input_field in self.input_fields: - if input_field.child_invalid: - return True - return False - - def get_invalid(self): - output = [] - for input_field in self.input_fields: - output.extend(input_field.get_invalid()) - return output - - def hierarchical_style_update(self): - for input_field in self.input_fields: - input_field.hierarchical_style_update() - self.update_style() - - def item_value(self): - output = {} - for input_field in self.input_fields: - # TODO maybe merge instead of update should be used - # NOTE merge is custom function which merges 2 dicts - output.update(input_field.config_value()) - return output - - def config_value(self): - return self.item_value() - - def studio_overrides(self): - if ( - not (self.as_widget or self.any_parent_as_widget) - and not self.has_studio_override - and not self.child_has_studio_override - ): - return NOT_SET, False - - values = {} - groups = [] - for input_field in self.input_fields: - value, is_group = input_field.studio_overrides() - if value is not NOT_SET: - values.update(value) - if is_group: - groups.extend(value.keys()) - if groups: - if METADATA_KEY not in values: - values[METADATA_KEY] = {} - values[METADATA_KEY]["groups"] = groups - return values, self.is_group - - def overrides(self): - if not self.is_overriden and not self.child_overriden: - return NOT_SET, False - - values = {} - groups = [] - for input_field in self.input_fields: - value, is_group = input_field.overrides() - if value is not NOT_SET: - values.update(value) - if is_group: - groups.extend(value.keys()) - if groups: - if METADATA_KEY not in values: - values[METADATA_KEY] = {} - values[METADATA_KEY]["groups"] = groups - return values, self.is_group - - -# Proxy for form layout -class FormLabel(QtWidgets.QLabel): - def __init__(self, input_field, *args, **kwargs): - super(FormLabel, self).__init__(*args, **kwargs) - self.input_field = input_field - - def mouseReleaseEvent(self, event): - if self.input_field: - return self.input_field.show_actions_menu(event) - return super(FormLabel, self).mouseReleaseEvent(event) - - -class FormItemWidget(WrapperItemWidget): - def create_ui(self, label_widget=None): - self.content_layout = QtWidgets.QFormLayout(self) - self.content_layout.setContentsMargins(0, 0, 0, 0) - - for child_data in self.schema_data["children"]: - self.add_children_gui(child_data) - - any_visible = False - for input_field in self.input_fields: - if not input_field.hidden_by_role: - any_visible = True - break - - if not any_visible: - self.hidden_by_role = True - self.hide() - - def add_children_gui(self, child_configuration): - item_type = child_configuration["type"] - # Pop label to not be set in child - label = child_configuration["label"] - - klass = TypeToKlass.types.get(item_type) - - item = klass(child_configuration, self) - - label_widget = FormLabel(item, label, self) - - item.create_ui(label_widget=label_widget) - - if item.hidden_by_role: - label_widget.hide() - - item.value_changed.connect(self._on_value_change) - self.content_layout.addRow(label_widget, item) - self.input_fields.append(item) - return item - - -class CollapsibleWrapperItem(WrapperItemWidget): - def wrapper_initial_attributes(self, schema_data): - self.collapsable = schema_data.get("collapsable", True) - self.collapsed = schema_data.get("collapsed", True) - - def create_ui(self, label_widget=None): - content_widget = QtWidgets.QWidget(self) - content_widget.setObjectName("ContentWidget") - content_widget.setProperty("content_state", "") - - content_layout = QtWidgets.QGridLayout(content_widget) - content_layout.setContentsMargins(CHILD_OFFSET, 5, 0, 0) - - body_widget = ExpandingWidget(self.schema_data["label"], self) - body_widget.set_content_widget(content_widget) - - label_widget = body_widget.label_widget - - main_layout = QtWidgets.QHBoxLayout(self) - main_layout.setContentsMargins(0, 0, 0, 0) - main_layout.setSpacing(0) - if not body_widget: - main_layout.addWidget(content_widget) - else: - main_layout.addWidget(body_widget) - - self.label_widget = label_widget - self.body_widget = body_widget - self.content_layout = content_layout - - if self.collapsable: - if not self.collapsed: - body_widget.toggle_content() - else: - body_widget.hide_toolbox(hide_content=False) - - for child_data in self.schema_data.get("children", []): - self.add_children_gui(child_data) - - any_visible = False - for input_field in self.input_fields: - if not input_field.hidden_by_role: - any_visible = True - break - - if not any_visible: - self.hide() - - def add_children_gui(self, child_configuration): - item_type = child_configuration["type"] - klass = TypeToKlass.types.get(item_type) - - row = self.content_layout.rowCount() - if not getattr(klass, "is_input_type", False): - item = klass(child_configuration, self) - self.content_layout.addWidget(item, row, 0, 1, 2) - return item - - label_widget = None - item = klass(child_configuration, self) - if not item.expand_in_grid: - label = child_configuration.get("label") - if label is not None: - label_widget = GridLabelWidget(label, self) - self.content_layout.addWidget(label_widget, row, 0, 1, 1) - - item.create_ui(label_widget=label_widget) - item.value_changed.connect(self._on_value_change) - - if label_widget: - if item.hidden_by_role: - label_widget.hide() - label_widget.input_field = item - self.content_layout.addWidget(item, row, 1, 1, 1) - else: - self.content_layout.addWidget(item, row, 0, 1, 2) - - self.input_fields.append(item) - return item - - def update_style(self, is_overriden=None): - child_has_studio_override = self.child_has_studio_override - child_modified = self.child_modified - child_invalid = self.child_invalid - child_state = self.style_state( - child_has_studio_override, - child_invalid, - self.child_overriden, - child_modified - ) - if child_state: - child_state = "child-{}".format(child_state) - - if child_state != self._child_state: - self.body_widget.side_line_widget.setProperty("state", child_state) - self.body_widget.side_line_widget.style().polish( - self.body_widget.side_line_widget - ) - self._child_state = child_state - - state = self.style_state( - self.had_studio_override, - child_invalid, - self.is_overriden, - self.is_modified - ) - if self._state == state: - return - - self.label_widget.setProperty("state", state) - self.label_widget.style().polish(self.label_widget) - - self._state = state - - -class LabelWidget(QtWidgets.QWidget): - is_input_type = False - - def __init__(self, configuration, parent): - super(LabelWidget, self).__init__(parent) - self.setObjectName("LabelWidget") - - label = configuration["label"] - - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 5, 0, 5) - label_widget = QtWidgets.QLabel(label, self) - layout.addWidget(label_widget) - - # Role handling - roles = configuration.get("roles") - if roles is not None and not isinstance(roles, list): - roles = [roles] - - if roles and parent.user_role not in roles: - self.hide() - self.hidden_by_role = True - else: - self.hidden_by_role = False - - -class SplitterWidget(QtWidgets.QWidget): - is_input_type = False - _height = 2 - - def __init__(self, configuration, parent): - super(SplitterWidget, self).__init__(parent) - - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(5, 5, 5, 5) - splitter_item = QtWidgets.QWidget(self) - splitter_item.setObjectName("SplitterItem") - splitter_item.setMinimumHeight(self._height) - splitter_item.setMaximumHeight(self._height) - layout.addWidget(splitter_item) - - # Role handling - roles = configuration.get("roles") - if roles is not None and not isinstance(roles, list): - roles = [roles] - - if roles and parent.user_role not in roles: - self.hide() - self.hidden_by_role = True - else: - self.hidden_by_role = False - - -TypeToKlass.types["boolean"] = BooleanWidget -TypeToKlass.types["number"] = NumberWidget -TypeToKlass.types["text"] = TextWidget -TypeToKlass.types["path-input"] = PathInputWidget -TypeToKlass.types["raw-json"] = RawJsonWidget -TypeToKlass.types["list"] = ListWidget -TypeToKlass.types["list-strict"] = ListStrictWidget -TypeToKlass.types["enum"] = EnumeratorWidget -TypeToKlass.types["dict-modifiable"] = ModifiableDict -# DEPRECATED - remove when removed from schemas -TypeToKlass.types["splitter"] = SplitterWidget -TypeToKlass.types["dict-item"] = DictWidget -# --------------------------------------------- -TypeToKlass.types["dict"] = DictWidget -TypeToKlass.types["path-widget"] = PathWidget - -# Wrappers -TypeToKlass.types["form"] = FormItemWidget -TypeToKlass.types["collapsible-wrap"] = CollapsibleWrapperItem - -# UI items -TypeToKlass.types["label"] = LabelWidget -TypeToKlass.types["separator"] = SplitterWidget From 39a6dcd8a97c00a92c8e06633aa47fecd013a010 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 15:18:31 +0100 Subject: [PATCH 26/83] added list_strict_widget.py with previous implementation --- .../settings/widgets/list_strict_widget.py | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 pype/tools/settings/settings/widgets/list_strict_widget.py diff --git a/pype/tools/settings/settings/widgets/list_strict_widget.py b/pype/tools/settings/settings/widgets/list_strict_widget.py new file mode 100644 index 0000000000..25be41c288 --- /dev/null +++ b/pype/tools/settings/settings/widgets/list_strict_widget.py @@ -0,0 +1,168 @@ +class ListStrictWidget(QtWidgets.QWidget, InputObject): + value_changed = QtCore.Signal(object) + _default_input_value = None + valid_value_types = (list, ) + + def __init__( + self, schema_data, parent, as_widget=False, parent_widget=None + ): + if parent_widget is None: + parent_widget = parent + super(ListStrictWidget, self).__init__(parent_widget) + self.setObjectName("ListStrictWidget") + + self.initial_attributes(schema_data, parent, as_widget) + + self.is_horizontal = schema_data.get("horizontal", True) + self.object_types = self.schema_data["object_types"] + + self.input_fields = [] + + def create_ui(self, label_widget=None): + layout = QtWidgets.QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 5) + layout.setSpacing(5) + + if not self.as_widget and not label_widget: + label = self.schema_data.get("label") + if label: + label_widget = QtWidgets.QLabel(label, self) + layout.addWidget(label_widget, alignment=QtCore.Qt.AlignTop) + elif self._is_group: + raise KeyError(( + "Schema item must contain \"label\" if `is_group` is True" + " to be able visualize changes and show actions." + )) + + self.label_widget = label_widget + + self._add_children(layout) + + def _add_children(self, layout): + inputs_widget = QtWidgets.QWidget(self) + inputs_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground) + layout.addWidget(inputs_widget) + + if self.is_horizontal: + inputs_layout = QtWidgets.QHBoxLayout(inputs_widget) + else: + inputs_layout = QtWidgets.QGridLayout(inputs_widget) + + inputs_layout.setContentsMargins(0, 0, 0, 0) + inputs_layout.setSpacing(3) + + self.inputs_widget = inputs_widget + self.inputs_layout = inputs_layout + + children_item_mapping = [] + for child_configuration in self.object_types: + item_widget = ListItem( + child_configuration, self, self.inputs_widget, is_strict=True + ) + + self.input_fields.append(item_widget) + item_widget.value_changed.connect(self._on_value_change) + + label = child_configuration.get("label") + label_widget = None + if label: + label_widget = QtWidgets.QLabel(label, self) + + children_item_mapping.append((label_widget, item_widget)) + + if self.is_horizontal: + self._add_children_horizontally(children_item_mapping) + else: + self._add_children_vertically(children_item_mapping) + + self.updateGeometry() + + def _add_children_vertically(self, children_item_mapping): + any_has_label = False + for item_mapping in children_item_mapping: + if item_mapping[0]: + any_has_label = True + break + + row = self.inputs_layout.count() + if not any_has_label: + self.inputs_layout.setColumnStretch(1, 1) + for item_mapping in children_item_mapping: + item_widget = item_mapping[1] + self.inputs_layout.addWidget(item_widget, row, 0, 1, 1) + + spacer_widget = QtWidgets.QWidget(self.inputs_widget) + self.inputs_layout.addWidget(spacer_widget, row, 1, 1, 1) + row += 1 + + else: + self.inputs_layout.setColumnStretch(2, 1) + for label_widget, item_widget in children_item_mapping: + self.inputs_layout.addWidget( + label_widget, row, 0, 1, 1, + alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignTop + ) + self.inputs_layout.addWidget(item_widget, row, 1, 1, 1) + + spacer_widget = QtWidgets.QWidget(self.inputs_widget) + self.inputs_layout.addWidget(spacer_widget, row, 2, 1, 1) + row += 1 + + def _add_children_horizontally(self, children_item_mapping): + for label_widget, item_widget in children_item_mapping: + if label_widget: + self.inputs_layout.addWidget(label_widget, 0) + self.inputs_layout.addWidget(item_widget, 0) + + spacer_widget = QtWidgets.QWidget(self.inputs_widget) + self.inputs_layout.addWidget(spacer_widget, 1) + + @property + def default_input_value(self): + if self._default_input_value is None: + self.set_value(NOT_SET) + self._default_input_value = self.item_value() + return self._default_input_value + + def set_value(self, value): + if self._is_overriden: + method_name = "apply_overrides" + elif not self._has_studio_override: + method_name = "update_default_values" + else: + method_name = "update_studio_values" + + for idx, input_field in enumerate(self.input_fields): + if value is NOT_SET: + _value = value + else: + if idx > len(value) - 1: + _value = NOT_SET + else: + _value = value[idx] + _method = getattr(input_field, method_name) + _method(_value) + + def hierarchical_style_update(self): + for input_field in self.input_fields: + input_field.hierarchical_style_update() + self.update_style() + + def update_style(self): + if not self.label_widget: + return + + state = self._style_state() + + if self._state == state: + return + + self._state = state + self.label_widget.setProperty("state", state) + self.label_widget.style().polish(self.label_widget) + + def item_value(self): + output = [] + for item in self.input_fields: + output.append(item.config_value()) + return output From f5d6e536e354104727e334b6df0446098b532068 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 15:52:30 +0100 Subject: [PATCH 27/83] basic list strict implementation --- .../settings/settings/widgets/categories.py | 3 +- .../settings/widgets/list_strict_widget.py | 212 +++++++----------- 2 files changed, 86 insertions(+), 129 deletions(-) diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index 5483e485a2..0c5ffe11e9 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -41,6 +41,7 @@ from . import lib from .base import GUIWidget from .list_item_widget import ListWidget +from .list_strict_widget import ListStrictWidget from .dict_mutable_widget import DictMutableKeysWidget from .item_widgets import ( BoolWidget, @@ -136,7 +137,7 @@ class SettingsCategoryWidget(QtWidgets.QWidget): return DictMutableKeysWidget(entity, entity_widget) elif isinstance(entity, ListStrictEntity): - pass + return ListStrictWidget(entity, entity_widget) label = "<{}>: {} ({})".format( entity.__class__.__name__, entity.path, entity.value diff --git a/pype/tools/settings/settings/widgets/list_strict_widget.py b/pype/tools/settings/settings/widgets/list_strict_widget.py index 25be41c288..82591b3ce8 100644 --- a/pype/tools/settings/settings/widgets/list_strict_widget.py +++ b/pype/tools/settings/settings/widgets/list_strict_widget.py @@ -1,168 +1,124 @@ -class ListStrictWidget(QtWidgets.QWidget, InputObject): - value_changed = QtCore.Signal(object) - _default_input_value = None - valid_value_types = (list, ) +from Qt import QtWidgets, QtCore - def __init__( - self, schema_data, parent, as_widget=False, parent_widget=None - ): - if parent_widget is None: - parent_widget = parent - super(ListStrictWidget, self).__init__(parent_widget) +from .widgets import ( + GridLabelWidget, + SpacerWidget +) +from .base import BaseWidget + + +class ListStrictWidget(BaseWidget): + def create_ui(self): self.setObjectName("ListStrictWidget") - self.initial_attributes(schema_data, parent, as_widget) - - self.is_horizontal = schema_data.get("horizontal", True) - self.object_types = self.schema_data["object_types"] - + self._child_style_state = "" self.input_fields = [] - def create_ui(self, label_widget=None): - layout = QtWidgets.QHBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 5) - layout.setSpacing(5) + content_layout = QtWidgets.QGridLayout(self) + content_layout.setContentsMargins(0, 0, 0, 0) + content_layout.setSpacing(3) - if not self.as_widget and not label_widget: - label = self.schema_data.get("label") - if label: - label_widget = QtWidgets.QLabel(label, self) - layout.addWidget(label_widget, alignment=QtCore.Qt.AlignTop) - elif self._is_group: - raise KeyError(( - "Schema item must contain \"label\" if `is_group` is True" - " to be able visualize changes and show actions." - )) + self.content_layout = content_layout + self.content_widget = self - self.label_widget = label_widget + any_children_has_label = False + for child_obj in self.entity.children: + if child_obj.label: + any_children_has_label = True + break - self._add_children(layout) + self._any_children_has_label = any_children_has_label + # Change column stretch factor for verticall alignment + if not self.entity.is_horizontal: + col_index = 2 if any_children_has_label else 1 + content_layout.setColumnStretch(col_index, 1) - def _add_children(self, layout): - inputs_widget = QtWidgets.QWidget(self) - inputs_widget.setAttribute(QtCore.Qt.WA_TranslucentBackground) - layout.addWidget(inputs_widget) - - if self.is_horizontal: - inputs_layout = QtWidgets.QHBoxLayout(inputs_widget) - else: - inputs_layout = QtWidgets.QGridLayout(inputs_widget) - - inputs_layout.setContentsMargins(0, 0, 0, 0) - inputs_layout.setSpacing(3) - - self.inputs_widget = inputs_widget - self.inputs_layout = inputs_layout - - children_item_mapping = [] - for child_configuration in self.object_types: - item_widget = ListItem( - child_configuration, self, self.inputs_widget, is_strict=True + for child_obj in self.entity.children: + self.input_fields.append( + self.create_ui_for_entity(child_obj, self) ) - self.input_fields.append(item_widget) - item_widget.value_changed.connect(self._on_value_change) + self.entity_widget.add_widget_to_layout(self, self.entity.label) - label = child_configuration.get("label") - label_widget = None - if label: - label_widget = QtWidgets.QLabel(label, self) + @property + def is_invalid(self): + return self._is_invalid or self._child_invalid - children_item_mapping.append((label_widget, item_widget)) + @property + def _child_invalid(self): + for input_field in self.input_fields: + if input_field.is_invalid: + return True + return False - if self.is_horizontal: - self._add_children_horizontally(children_item_mapping) + def add_widget_to_layout(self, widget, label=None): + # Horizontally added children + if self.entity.is_horizontal: + self._add_child_horizontally(widget, label) else: - self._add_children_vertically(children_item_mapping) + self._add_child_vertically(widget, label) self.updateGeometry() - def _add_children_vertically(self, children_item_mapping): - any_has_label = False - for item_mapping in children_item_mapping: - if item_mapping[0]: - any_has_label = True - break + def _add_child_horizontally(self, widget, label): + row = self.content_layout.rowCount() + # Expand to whole grid if all children are without label + if not self._any_children_has_label: + self.content_layout.addWidget(widget, row, 0, 1, 2) + else: + if label: + label_widget = GridLabelWidget(label, widget) + label_widget.input_field = widget + widget.label_widget = label_widget + self.content_layout.addWidget(label_widget, row, 0, 1, 1) + self.content_layout.addWidget(widget, row, 1, 1, 1) - row = self.inputs_layout.count() - if not any_has_label: - self.inputs_layout.setColumnStretch(1, 1) - for item_mapping in children_item_mapping: - item_widget = item_mapping[1] - self.inputs_layout.addWidget(item_widget, row, 0, 1, 1) + def _add_child_vertically(self, widget, label): + row = self.content_layout.rowCount() + if not self._any_children_has_label: + self.content_layout.addWidget(widget, row, 0, 1, 1) - spacer_widget = QtWidgets.QWidget(self.inputs_widget) - self.inputs_layout.addWidget(spacer_widget, row, 1, 1, 1) - row += 1 + spacer_widget = SpacerWidget(self) + self.content_layout.addWidget(spacer_widget, row, 1, 1, 1) else: - self.inputs_layout.setColumnStretch(2, 1) - for label_widget, item_widget in children_item_mapping: - self.inputs_layout.addWidget( + if label: + label_widget = GridLabelWidget(label, widget) + label_widget.input_field = widget + widget.label_widget = label_widget + self.content_layout.addWidget( label_widget, row, 0, 1, 1, alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignTop ) - self.inputs_layout.addWidget(item_widget, row, 1, 1, 1) + self.content_layout.addWidget(widget, row, 1, 1, 1) - spacer_widget = QtWidgets.QWidget(self.inputs_widget) - self.inputs_layout.addWidget(spacer_widget, row, 2, 1, 1) - row += 1 - - def _add_children_horizontally(self, children_item_mapping): - for label_widget, item_widget in children_item_mapping: - if label_widget: - self.inputs_layout.addWidget(label_widget, 0) - self.inputs_layout.addWidget(item_widget, 0) - - spacer_widget = QtWidgets.QWidget(self.inputs_widget) - self.inputs_layout.addWidget(spacer_widget, 1) - - @property - def default_input_value(self): - if self._default_input_value is None: - self.set_value(NOT_SET) - self._default_input_value = self.item_value() - return self._default_input_value - - def set_value(self, value): - if self._is_overriden: - method_name = "apply_overrides" - elif not self._has_studio_override: - method_name = "update_default_values" - else: - method_name = "update_studio_values" - - for idx, input_field in enumerate(self.input_fields): - if value is NOT_SET: - _value = value - else: - if idx > len(value) - 1: - _value = NOT_SET - else: - _value = value[idx] - _method = getattr(input_field, method_name) - _method(_value) + spacer_widget = SpacerWidget(self) + self.content_layout.addWidget(spacer_widget, row, 2, 1, 1) def hierarchical_style_update(self): + self.update_style() for input_field in self.input_fields: input_field.hierarchical_style_update() - self.update_style() + + def set_entity_value(self): + for input_field in self.input_fields: + input_field.set_entity_value() def update_style(self): if not self.label_widget: return - state = self._style_state() + style_state = self.get_style_state( + self.is_invalid, + self.entity.has_unsaved_changes, + self.entity.has_project_override, + self.entity.has_studio_override + ) - if self._state == state: + if self._style_state == style_state: return - self._state = state - self.label_widget.setProperty("state", state) + self.label_widget.setProperty("state", style_state) self.label_widget.style().polish(self.label_widget) - def item_value(self): - output = [] - for item in self.input_fields: - output.append(item.config_value()) - return output + self._style_state = style_state From 608a81de82dd5141dc35eac366ec8ba2ead4a5f0 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 15:52:43 +0100 Subject: [PATCH 28/83] modified private attributes --- pype/tools/settings/settings/widgets/item_widgets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/tools/settings/settings/widgets/item_widgets.py b/pype/tools/settings/settings/widgets/item_widgets.py index c4918a3f9a..162dac266d 100644 --- a/pype/tools/settings/settings/widgets/item_widgets.py +++ b/pype/tools/settings/settings/widgets/item_widgets.py @@ -231,10 +231,10 @@ class DictImmutableKeysWidget(BaseWidget): @property def is_invalid(self): - return self._is_invalid or self.child_invalid + return self._is_invalid or self._child_invalid @property - def child_invalid(self): + def _child_invalid(self): for input_field in self.input_fields: if input_field.is_invalid: return True From 7e130201f7ee84ab949c1f2ba405c56b86e21ef4 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:01:31 +0100 Subject: [PATCH 29/83] fixed horizontal layout in strict list --- .../settings/widgets/list_strict_widget.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pype/tools/settings/settings/widgets/list_strict_widget.py b/pype/tools/settings/settings/widgets/list_strict_widget.py index 82591b3ce8..cf3ffc22f7 100644 --- a/pype/tools/settings/settings/widgets/list_strict_widget.py +++ b/pype/tools/settings/settings/widgets/list_strict_widget.py @@ -38,6 +38,12 @@ class ListStrictWidget(BaseWidget): self.create_ui_for_entity(child_obj, self) ) + if self.entity.is_horizontal: + col = self.content_layout.columnCount() + spacer = SpacerWidget(self) + self.content_layout.addWidget(spacer, 0, col, 2, 1) + self.content_layout.setColumnStretch(col, 1) + self.entity_widget.add_widget_to_layout(self, self.entity.label) @property @@ -61,17 +67,18 @@ class ListStrictWidget(BaseWidget): self.updateGeometry() def _add_child_horizontally(self, widget, label): - row = self.content_layout.rowCount() + col = self.content_layout.columnCount() # Expand to whole grid if all children are without label if not self._any_children_has_label: - self.content_layout.addWidget(widget, row, 0, 1, 2) + self.content_layout.addWidget(widget, 0, col, 1, 2) else: if label: label_widget = GridLabelWidget(label, widget) label_widget.input_field = widget widget.label_widget = label_widget - self.content_layout.addWidget(label_widget, row, 0, 1, 1) - self.content_layout.addWidget(widget, row, 1, 1, 1) + self.content_layout.addWidget(label_widget, 0, col, 1, 1) + col += 1 + self.content_layout.addWidget(widget, 0, col, 1, 1) def _add_child_vertically(self, widget, label): row = self.content_layout.rowCount() From 68ff323978c4ed7440cfd2dfd8c696794c6aa2e8 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:07:06 +0100 Subject: [PATCH 30/83] fix has unsaved changes --- pype/settings/entities/item_entities.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pype/settings/entities/item_entities.py b/pype/settings/entities/item_entities.py index 2fec667749..ffdee0fb8d 100644 --- a/pype/settings/entities/item_entities.py +++ b/pype/settings/entities/item_entities.py @@ -266,6 +266,7 @@ class ListStrictEntity(ItemEntity): self.on_change() + @property def has_unsaved_changes(self): if self._override_state is OverrideState.NOT_DEFINED: return False From 95d158d5577aa4b070c233bd4f80ad8befdde913 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:10:47 +0100 Subject: [PATCH 31/83] added file item validation for list strict item --- pype/settings/entities/input_entities.py | 2 +- pype/settings/entities/item_entities.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pype/settings/entities/input_entities.py b/pype/settings/entities/input_entities.py index ce512519a1..caa2b5b1e3 100644 --- a/pype/settings/entities/input_entities.py +++ b/pype/settings/entities/input_entities.py @@ -101,7 +101,7 @@ class InputEntity(EndpointEntity): "{}: Missing parent file entity.".format(self.path) ) - super(EndpointEntity, self).schema_validations() + super(InputEntity, self).schema_validations() @property def value(self): diff --git a/pype/settings/entities/item_entities.py b/pype/settings/entities/item_entities.py index ffdee0fb8d..1692c3bf42 100644 --- a/pype/settings/entities/item_entities.py +++ b/pype/settings/entities/item_entities.py @@ -206,6 +206,15 @@ class ListStrictEntity(ItemEntity): if not self.group_item and not self.is_group: self.is_group = True + def schema_validations(self): + # List entity must have file parent. + if not self.file_item and not self.is_file: + raise ValueError( + "{}: Missing file entity in hierarchy.".format(self.path) + ) + + super(ListStrictEntity, self).schema_validations() + def get_child_path(self, child_obj): result_idx = None for idx, _child_obj in enumerate(self.children): From 4a154dcd449fe9e2424b33f850ed2bcd9a86842d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:14:51 +0100 Subject: [PATCH 32/83] fix attribute names --- pype/settings/entities/item_entities.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/settings/entities/item_entities.py b/pype/settings/entities/item_entities.py index 1692c3bf42..6d484b09b8 100644 --- a/pype/settings/entities/item_entities.py +++ b/pype/settings/entities/item_entities.py @@ -269,9 +269,9 @@ class ListStrictEntity(ItemEntity): return if self._override_state is OverrideState.STUDIO: - self._has_studio_override = self.child_has_studio_override + self._has_studio_override = self._child_has_studio_override elif self._override_state is OverrideState.PROJECT: - self._has_project_override = self.child_has_project_override + self._has_project_override = self._child_has_project_override self.on_change() From eb63cb85a6287ec860f49a46ac2a49448eb8c10e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:14:58 +0100 Subject: [PATCH 33/83] implemented get_invalid method --- pype/tools/settings/settings/widgets/list_strict_widget.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pype/tools/settings/settings/widgets/list_strict_widget.py b/pype/tools/settings/settings/widgets/list_strict_widget.py index cf3ffc22f7..b6bf325e1a 100644 --- a/pype/tools/settings/settings/widgets/list_strict_widget.py +++ b/pype/tools/settings/settings/widgets/list_strict_widget.py @@ -57,6 +57,12 @@ class ListStrictWidget(BaseWidget): return True return False + def get_invalid(self): + invalid = [] + for input_field in self.input_fields: + invalid.extend(input_field.get_invalid()) + return invalid + def add_widget_to_layout(self, widget, label=None): # Horizontally added children if self.entity.is_horizontal: From 71b4b75e9490a853543be53bf3e9684663d1e0c7 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:26:47 +0100 Subject: [PATCH 34/83] fixed auto is_group setting and added validation for is_group input --- pype/settings/entities/base_entity.py | 8 ++++++++ pype/settings/entities/input_entities.py | 5 ++++- pype/settings/entities/item_entities.py | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pype/settings/entities/base_entity.py b/pype/settings/entities/base_entity.py index 4eef866b17..d15586343c 100644 --- a/pype/settings/entities/base_entity.py +++ b/pype/settings/entities/base_entity.py @@ -247,6 +247,14 @@ class BaseItemEntity(BaseEntity): "{}: Item has set label but is used as dynamic item." ).format(self.path)) + # Dynamic items or items in dynamic item must not have set `is_group` + if self.is_group and (self.is_dynamic_item or self.is_in_dynamic_item): + raise ValueError( + "{} Dynamic entity has set `is_group` to true.".format( + self.path + ) + ) + @abstractmethod def set_override_state(self, state): """Set override state and trigger it on children. diff --git a/pype/settings/entities/input_entities.py b/pype/settings/entities/input_entities.py index caa2b5b1e3..145c9ac811 100644 --- a/pype/settings/entities/input_entities.py +++ b/pype/settings/entities/input_entities.py @@ -24,7 +24,10 @@ class EndpointEntity(ItemEntity): def __init__(self, *args, **kwargs): super(EndpointEntity, self).__init__(*args, **kwargs) - if not self.group_item and not self.is_group: + if ( + not (self.group_item or self.is_group) + and not (self.is_dynamic_item or self.is_in_dynamic_item) + ): self.is_group = True def schema_validations(self): diff --git a/pype/settings/entities/item_entities.py b/pype/settings/entities/item_entities.py index 6d484b09b8..409f031afb 100644 --- a/pype/settings/entities/item_entities.py +++ b/pype/settings/entities/item_entities.py @@ -342,8 +342,8 @@ class ListStrictEntity(ItemEntity): if not self.is_dynamic_item and not self.is_in_dynamic_item: raise DefaultsNotDefined(self) - for child_obj in self.children: - child_obj.set_override_state(state) + for child_entity in self.children: + child_entity.set_override_state(state) self.initial_value = self.settings_value() From 795e15b0114dca19391c3008ecf7e9f99f2c5128 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:35:48 +0100 Subject: [PATCH 35/83] pass changes in list strict widget --- pype/tools/settings/settings/widgets/list_strict_widget.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pype/tools/settings/settings/widgets/list_strict_widget.py b/pype/tools/settings/settings/widgets/list_strict_widget.py index b6bf325e1a..1167bf4cdb 100644 --- a/pype/tools/settings/settings/widgets/list_strict_widget.py +++ b/pype/tools/settings/settings/widgets/list_strict_widget.py @@ -117,6 +117,9 @@ class ListStrictWidget(BaseWidget): for input_field in self.input_fields: input_field.set_entity_value() + def _on_entity_change(self): + pass + def update_style(self): if not self.label_widget: return From f97763d4efea24d16f5b69bb6c418e9a97cb5a33 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:38:06 +0100 Subject: [PATCH 36/83] fix message typo --- pype/tools/settings/settings/widgets/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/tools/settings/settings/widgets/base.py b/pype/tools/settings/settings/widgets/base.py index aaeb736c0a..acebba0e3a 100644 --- a/pype/tools/settings/settings/widgets/base.py +++ b/pype/tools/settings/settings/widgets/base.py @@ -59,7 +59,7 @@ class BaseWidget(QtWidgets.QWidget): def _on_entity_change(self): """Not yet used.""" - print("{}: Wraning missing `_on_entity_change` implementation".format( + print("{}: Warning missing `_on_entity_change` implementation".format( self.__class__.__name__ )) From 41d12e6103e84a0af4fe629d4450e03ac58a2714 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:42:36 +0100 Subject: [PATCH 37/83] fixed modifiable dict layout spacing --- .../tools/settings/settings/widgets/dict_mutable_widget.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pype/tools/settings/settings/widgets/dict_mutable_widget.py b/pype/tools/settings/settings/widgets/dict_mutable_widget.py index a9e11f051c..a4159a99de 100644 --- a/pype/tools/settings/settings/widgets/dict_mutable_widget.py +++ b/pype/tools/settings/settings/widgets/dict_mutable_widget.py @@ -182,9 +182,6 @@ class ModifiableDictItem(QtWidgets.QWidget): key_input = QtWidgets.QLineEdit(self) key_input.setObjectName("DictKey") - spacer_widget = SpacerWidget(self) - spacer_widget.setVisible(False) - add_btn = create_add_btn(self) remove_btn = create_remove_btn(self) @@ -194,7 +191,6 @@ class ModifiableDictItem(QtWidgets.QWidget): layout.addWidget(add_btn, 0) layout.addWidget(remove_btn, 0) layout.addWidget(key_input, 0) - layout.addWidget(spacer_widget, 1) key_input.textChanged.connect(self._on_key_change) key_input.returnPressed.connect(self._on_enter_press) @@ -203,7 +199,6 @@ class ModifiableDictItem(QtWidgets.QWidget): remove_btn.clicked.connect(self.on_remove_clicked) self.key_input = key_input - self.spacer_widget = spacer_widget self.add_btn = add_btn self.remove_btn = remove_btn @@ -213,7 +208,7 @@ class ModifiableDictItem(QtWidgets.QWidget): self.input_field = self.create_ui_for_entity(self.entity, self) def add_widget_to_layout(self, widget, label=None): - self.content_layout.addWidget(widget) + self.content_layout.addWidget(widget, 1) self.setFocusProxy(widget) def create_collapsible_ui(self): From 3ec8940125656119f0349ae43e6196dbe4d3a368 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:44:40 +0100 Subject: [PATCH 38/83] imports cleanup --- pype/tools/settings/settings/widgets/categories.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index 0c5ffe11e9..9fcde564d7 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -1,11 +1,7 @@ import os -import json from enum import Enum from Qt import QtWidgets, QtCore, QtGui -from pype.settings.constants import ( - PROJECT_SETTINGS_KEY, - PROJECT_ANATOMY_KEY -) + from pype.settings.entities import ( SystemSettings, ProjectSettings, @@ -27,12 +23,7 @@ from pype.settings.entities import ( DefaultsNotDefined ) -from pype.settings.lib import ( - reset_default_settings, - get_default_settings, - - get_system_settings -) +from pype.settings.lib import get_system_settings from .widgets import ( UnsavedChangesDialog, ProjectListWidget From 6e1365375bc7442285c6e897a09c8605cd324be6 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:46:31 +0100 Subject: [PATCH 39/83] fix widgets visibility --- .../tools/settings/settings/widgets/dict_mutable_widget.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pype/tools/settings/settings/widgets/dict_mutable_widget.py b/pype/tools/settings/settings/widgets/dict_mutable_widget.py index a4159a99de..63f0ee539a 100644 --- a/pype/tools/settings/settings/widgets/dict_mutable_widget.py +++ b/pype/tools/settings/settings/widgets/dict_mutable_widget.py @@ -270,6 +270,13 @@ class ModifiableDictItem(QtWidgets.QWidget): edit_btn.clicked.connect(self.on_edit_pressed) remove_btn.clicked.connect(self.on_remove_clicked) + # Hide edit inputs + key_input.setVisible(False) + key_input_label_widget.setVisible(False) + key_label_input.setVisible(False) + key_label_input_label_widget.setVisible(False) + remove_btn.setVisible(False) + self.key_input = key_input self.key_input_label_widget = key_input_label_widget self.key_label_input = key_label_input From ac26f27f5aedb487d7bf6f482f48e73a1db85973 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 16:53:01 +0100 Subject: [PATCH 40/83] renamed `set_value_for_key` to `set_key_value` --- pype/settings/entities/dict_mutable_keys_entity.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index 833b49f100..bb7089364e 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -22,7 +22,7 @@ class DictMutableKeysEntity(EndpointEntity): return self.children_by_key[key] def __setitem__(self, key, value): - self.set_value_for_key(key, value) + self.set_key_value(key, value) def __iter__(self): for key in self.keys(): @@ -58,14 +58,14 @@ class DictMutableKeysEntity(EndpointEntity): prev_keys = set(self.keys()) for _key, _value in value.items(): - self.set_value_for_key(_key, _value) + self.set_key_value(_key, _value) if _key in prev_keys: prev_keys.remove(_key) for key in prev_keys: self.pop(key) - def set_value_for_key(self, key, value): + def set_key_value(self, key, value): # TODO Check for value type if is Settings entity? child_obj = self.children_by_key.get(key) if not child_obj: From 2bd691ce5fda6d24e4928f9f9b95fcf89863369e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 17:03:22 +0100 Subject: [PATCH 41/83] added methods for label manipulation in mutable keys dict --- .../entities/dict_mutable_keys_entity.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index bb7089364e..da0e60b6c3 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -114,6 +114,22 @@ class DictMutableKeysEntity(EndpointEntity): return key return None + # Label methods + def get_child_label(self, child_entity): + return self.children_label_by_id.get(child_entity.id) + + def set_child_label(self, child_entity, label): + self.children_label_by_id[child_entity.id] = label + self.on_change() + + def get_key_label(self, key): + child_entity = self.children_by_key[key] + return self.get_child_label(child_entity) + + def set_key_label(self, key, label): + child_entity = self.children_by_key[key] + self.set_child_label(child_entity, label) + def _item_initalization(self): self._default_metadata = {} self._studio_override_metadata = {} @@ -368,6 +384,8 @@ class DictMutableKeysEntity(EndpointEntity): output = {} for key, child_entity in self.children_by_key.items(): child_value = child_entity.settings_value() + # TODO child should have setter of env group key se child can + # know what env group represents. if self.value_is_env_group: if key not in child_value[M_ENVIRONMENT_KEY]: _metadata = child_value[M_ENVIRONMENT_KEY] From 6dabce123267f196ccc2930d261bc5079e762595 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 17:40:28 +0100 Subject: [PATCH 42/83] fix defaults dir of project settings --- pype/settings/entities/root_entities.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index e94d7c975d..0d0eef01b1 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -647,7 +647,7 @@ class ProjectSettings(RootEntity): Implementation of abstract method. """ - return os.path.join(DEFAULTS_DIR, SYSTEM_SETTINGS_KEY) + return DEFAULTS_DIR def _save_studio_values(self): settings_value = self.settings_value() From f7c7cfe6129a4137dfdcdc195bcf315df6458e14 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 17:40:45 +0100 Subject: [PATCH 43/83] modified override attributes of list strict entity --- pype/settings/entities/item_entities.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pype/settings/entities/item_entities.py b/pype/settings/entities/item_entities.py index 409f031afb..f7b1b07e0e 100644 --- a/pype/settings/entities/item_entities.py +++ b/pype/settings/entities/item_entities.py @@ -309,6 +309,14 @@ class ListStrictEntity(ItemEntity): return True return False + @property + def has_studio_override(self): + return self._has_studio_override or self._child_has_studio_override + + @property + def has_project_override(self): + return self._has_project_override or self._child_has_project_override + @property def _child_has_unsaved_changes(self): for child_obj in self.children: From 6392ac8b11c773d729e3dd72fe926e5366676104 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 17:41:18 +0100 Subject: [PATCH 44/83] fix labels metadata in standalone publisher --- .../project_settings/standalonepublisher.json | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pype/settings/defaults/project_settings/standalonepublisher.json b/pype/settings/defaults/project_settings/standalonepublisher.json index 67b4826692..ad1b5e82b2 100644 --- a/pype/settings/defaults/project_settings/standalonepublisher.json +++ b/pype/settings/defaults/project_settings/standalonepublisher.json @@ -10,18 +10,6 @@ } }, "create": { - "__dynamic_keys_labels__": { - "create_workfile": "Workfile", - "create_model": "Model", - "create_rig": "Rig", - "create_pointcache": "Pointcache", - "create_plate": "Plate", - "create_camera": "Camera", - "create_editorial": "Editorial", - "create_image": "Image", - "create_matchmove": "Matchmove", - "": "" - }, "create_workfile": { "name": "workfile", "label": "Workfile", @@ -121,6 +109,17 @@ "Mocap" ], "help": "Script exported from matchmoving application" + }, + "__dynamic_keys_labels__": { + "create_workfile": "Workfile", + "create_model": "Model", + "create_rig": "Rig", + "create_pointcache": "Pointcache", + "create_plate": "Plate", + "create_camera": "Camera", + "create_editorial": "Editorial", + "create_image": "Image", + "create_matchmove": "Matchmove" } } } \ No newline at end of file From d0a4b7c722f1ec5895b24560e6c4766226491af9 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 18:55:20 +0100 Subject: [PATCH 45/83] modified immutable dict attribute filtering --- .../entities/dict_immutable_keys_entity.py | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/pype/settings/entities/dict_immutable_keys_entity.py b/pype/settings/entities/dict_immutable_keys_entity.py index 9379d43325..a36741d930 100644 --- a/pype/settings/entities/dict_immutable_keys_entity.py +++ b/pype/settings/entities/dict_immutable_keys_entity.py @@ -282,17 +282,18 @@ class DictImmutableKeysEntity(ItemEntity): if self._metadata_are_modified: return True - if ( - self._override_state is OverrideState.PROJECT - and self._has_project_override != self.had_project_override - ): - return True + if self.is_group or self.group_item: + if ( + self._override_state is OverrideState.PROJECT + and self._has_project_override != self.had_project_override + ): + return True - elif ( - self._override_state is OverrideState.STUDIO - and self._has_studio_override != self.had_studio_override - ): - return True + elif ( + self._override_state is OverrideState.STUDIO + and self._has_studio_override != self.had_studio_override + ): + return True return self._child_has_unsaved_changes @@ -305,6 +306,8 @@ class DictImmutableKeysEntity(ItemEntity): @property def has_studio_override(self): + if not self.is_group and not self.group_item: + return self._child_has_studio_override return self._has_studio_override or self._child_has_studio_override @property @@ -317,6 +320,8 @@ class DictImmutableKeysEntity(ItemEntity): @property def has_project_override(self): + if not self.is_group and not self.group_item: + return self._child_has_project_override return self._has_project_override or self._child_has_project_override @property From c48ddbc54f757857308a1ce3cb433c96fa9085c7 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 18:55:49 +0100 Subject: [PATCH 46/83] fix project saving --- pype/settings/entities/root_entities.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index 0d0eef01b1..73c38ff750 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -592,16 +592,6 @@ class ProjectSettings(RootEntity): self.log.warning("change_project not implemented yet!") def _reset_values(self): - - # PROJECT_SETTINGS_KEY, - # PROJECT_ANATOMY_KEY - # get_studio_project_settings_overrides, - # get_studio_project_anatomy_overrides, - # get_project_settings_overrides, - # get_project_anatomy_overrides, - # save_project_settings, - # save_project_anatomy, - default_values = { PROJECT_SETTINGS_KEY: get_default_settings()[PROJECT_SETTINGS_KEY], PROJECT_ANATOMY_KEY: get_default_settings()[PROJECT_ANATOMY_KEY] @@ -614,6 +604,7 @@ class ProjectSettings(RootEntity): PROJECT_SETTINGS_KEY: get_studio_project_settings_overrides(), PROJECT_ANATOMY_KEY: get_studio_project_anatomy_overrides() } + for key, child_obj in self.non_gui_children.items(): value = studio_overrides.get(key, NOT_SET) child_obj.update_studio_values(value) @@ -657,7 +648,11 @@ class ProjectSettings(RootEntity): self.log.debug("Saving system settings: {}".format( json.dumps(settings_value, indent=4) )) - save_studio_settings(settings_value) + project_settings = settings_value.get(PROJECT_SETTINGS_KEY) or {} + project_anatomy = settings_value.get(PROJECT_ANATOMY_KEY) or {} + + save_project_settings(self.project_name, project_settings) + save_project_anatomy(self.project_name, project_anatomy) def _validate_defaults_to_save(self, value): """Valiations of default values before save.""" From 83f98950445c03f14ed529502623103509e1f6dc Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 19:10:53 +0100 Subject: [PATCH 47/83] modified attribute check --- pype/settings/entities/dict_immutable_keys_entity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/settings/entities/dict_immutable_keys_entity.py b/pype/settings/entities/dict_immutable_keys_entity.py index a36741d930..a6b1a6f1cd 100644 --- a/pype/settings/entities/dict_immutable_keys_entity.py +++ b/pype/settings/entities/dict_immutable_keys_entity.py @@ -350,10 +350,10 @@ class DictImmutableKeysEntity(ItemEntity): if self.is_group: if self._override_state is OverrideState.STUDIO: - if not self._has_studio_override: + if not self.has_studio_override: return NOT_SET elif self._override_state is OverrideState.PROJECT: - if not self._has_project_override: + if not self.has_project_override: return NOT_SET output = {} From f43122084fb9ad700f5b3fa1b041db222e5914de Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 19:11:17 +0100 Subject: [PATCH 48/83] added some docstring --- pype/settings/entities/dict_mutable_keys_entity.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index da0e60b6c3..ca7a3ee3a6 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -14,7 +14,17 @@ from pype.settings.constants import ( class DictMutableKeysEntity(EndpointEntity): - """""" + """Dictionary entity that has mutable keys. + + Keys of entity's children can be modified, removed or added. Children have + defined entity type so it is not possible to have 2 different entity types + as children. + + TODOs: + - cleanup children on pop + - remove child's reference to parent + - clear callbacks + """ schema_types = ["dict-modifiable"] _miss_arg = object() From 5b8c197b588ea8f1455b4a7a632b611478dfd65a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 19:23:33 +0100 Subject: [PATCH 49/83] project settings can load and save project overrides --- pype/settings/entities/root_entities.py | 40 +++++++++++++++++-------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index 73c38ff750..5fde2bc177 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -588,8 +588,21 @@ class ProjectSettings(RootEntity): def change_project(self, project_name): if project_name == self._project_name: return - # TODO implement - self.log.warning("change_project not implemented yet!") + + self._project_name = project_name + if project_name is None: + self.set_studio_state() + return + + project_override_value = { + PROJECT_SETTINGS_KEY: get_project_settings_overrides(project_name), + PROJECT_ANATOMY_KEY: get_project_anatomy_overrides(project_name) + } + for key, child_obj in self.non_gui_children.items(): + value = project_override_value.get(key, NOT_SET) + child_obj.update_project_values(value) + + self.set_project_state() def _reset_values(self): default_values = { @@ -612,6 +625,15 @@ class ProjectSettings(RootEntity): if not self.project_name: return + project_name = self.project_name + project_override_value = { + PROJECT_SETTINGS_KEY: get_project_settings_overrides(project_name), + PROJECT_ANATOMY_KEY: get_project_anatomy_overrides(project_name) + } + for key, child_obj in self.non_gui_children.items(): + value = project_override_value.get(key, NOT_SET) + child_obj.update_project_values(value) + def reset(self, new_state=None): """Discard changes and reset entit's values. @@ -627,9 +649,6 @@ class ProjectSettings(RootEntity): if new_state is OverrideState.NOT_DEFINED: new_state = OverrideState.DEFAULTS - if new_state is OverrideState.PROJECT: - raise ValueError("System settings can't store poject overrides.") - self._reset_values() self.set_override_state(new_state) @@ -645,7 +664,7 @@ class ProjectSettings(RootEntity): self._validate_values_to_save(settings_value) - self.log.debug("Saving system settings: {}".format( + self.log.debug("Saving project settings: {}".format( json.dumps(settings_value, indent=4) )) project_settings = settings_value.get(PROJECT_SETTINGS_KEY) or {} @@ -662,10 +681,5 @@ class ProjectSettings(RootEntity): pass def _save_project_values(self): - """System settings can't have project overrides. - - Raises: - ValueError: Raise when called as entity can't use or store project - overrides. - """ - self.log.warning("_save_project_values not implemented") + """Project overrides are saved same ways as studio overrides.""" + self._save_studio_values() From f559ddd44bb597145cdcae0d4341b5a4b4e113da Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Tue, 16 Feb 2021 19:23:53 +0100 Subject: [PATCH 50/83] fixed project change in project category --- pype/tools/settings/settings/widgets/categories.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index 9fcde564d7..c1964faebf 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -429,9 +429,10 @@ class ProjectWidget(SettingsCategoryWidget): elif self.project_name is None: self.entity.set_studio_state() + elif self.project_name == self.entity.project_name: + self.entity.set_project_state() else: self.entity.change_project(self.project_name) - self.entity.set_project_state() if self.modify_defaults_checkbox: self.modify_defaults_checkbox.setEnabled(True) @@ -454,9 +455,10 @@ class ProjectWidget(SettingsCategoryWidget): if project_name == self.project_name: return + self.project_name = project_name + self.set_state(CategoryState.Working) - self.entity.change_project(project_name) self.reset() self.set_state(CategoryState.Idle) From 73f16955c5dbe0e667f7e5f7e10d05083b3a4634 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 09:33:49 +0100 Subject: [PATCH 51/83] renamed update methods --- pype/settings/entities/base_entity.py | 4 ++-- .../entities/dict_immutable_keys_entity.py | 12 +++++------ .../entities/dict_mutable_keys_entity.py | 8 ++++---- pype/settings/entities/input_entities.py | 8 ++++---- pype/settings/entities/item_entities.py | 20 +++++++++---------- pype/settings/entities/list_entity.py | 14 ++++++------- pype/settings/entities/root_entities.py | 8 ++++---- 7 files changed, 37 insertions(+), 37 deletions(-) diff --git a/pype/settings/entities/base_entity.py b/pype/settings/entities/base_entity.py index d15586343c..49fd24aae8 100644 --- a/pype/settings/entities/base_entity.py +++ b/pype/settings/entities/base_entity.py @@ -638,7 +638,7 @@ class ItemEntity(BaseItemEntity): pass @abstractmethod - def update_studio_values(self, parent_values): + def update_studio_value(self, parent_values): """Fill studio override values on startup or on refresh. Set studio value if is not set to NOT_SET, in that case studio @@ -651,7 +651,7 @@ class ItemEntity(BaseItemEntity): pass @abstractmethod - def update_project_values(self, parent_values): + def update_project_value(self, parent_values): """Fill project override values on startup, refresh or project change. Set project value if is not set to NOT_SET, in that case project diff --git a/pype/settings/entities/dict_immutable_keys_entity.py b/pype/settings/entities/dict_immutable_keys_entity.py index a6b1a6f1cd..3fb6f563cb 100644 --- a/pype/settings/entities/dict_immutable_keys_entity.py +++ b/pype/settings/entities/dict_immutable_keys_entity.py @@ -411,7 +411,7 @@ class DictImmutableKeysEntity(ItemEntity): child_value = value.get(key, NOT_SET) child_obj.update_default_value(child_value) - def update_studio_values(self, value): + def update_studio_value(self, value): """Update studio override values. Not an api method, should be called by parent. @@ -422,7 +422,7 @@ class DictImmutableKeysEntity(ItemEntity): if value is NOT_SET: for child_obj in self.non_gui_children.values(): - child_obj.update_studio_values(value) + child_obj.update_studio_value(value) return value_keys = set(value.keys()) @@ -437,9 +437,9 @@ class DictImmutableKeysEntity(ItemEntity): ) for key, child_obj in self.non_gui_children.items(): child_value = value.get(key, NOT_SET) - child_obj.update_studio_values(child_value) + child_obj.update_studio_value(child_value) - def update_project_values(self, value): + def update_project_value(self, value): """Update project override values. Not an api method, should be called by parent. @@ -450,7 +450,7 @@ class DictImmutableKeysEntity(ItemEntity): if value is NOT_SET: for child_obj in self.non_gui_children.values(): - child_obj.update_project_values(value) + child_obj.update_project_value(value) return value_keys = set(value.keys()) @@ -466,7 +466,7 @@ class DictImmutableKeysEntity(ItemEntity): for key, child_obj in self.non_gui_children.items(): child_value = value.get(key, NOT_SET) - child_obj.update_project_values(child_value) + child_obj.update_project_value(child_value) def _discard_changes(self, on_change_trigger): self._ignore_child_changes = True diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index ca7a3ee3a6..9a016b3afc 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -292,9 +292,9 @@ class DictMutableKeysEntity(EndpointEntity): child_obj.update_default_value(_value) if using_overrides: if state is OverrideState.STUDIO: - child_obj.update_studio_values(_value) + child_obj.update_studio_value(_value) else: - child_obj.update_project_values(_value) + child_obj.update_project_value(_value) label = metadata_labels.get(_key) if label: @@ -421,14 +421,14 @@ class DictMutableKeysEntity(EndpointEntity): self._default_value = value self._default_metadata = metadata - def update_studio_values(self, value): + def update_studio_value(self, value): value = self._check_update_value(value, "studio override") value, metadata = self._prepare_value(value) self._studio_override_value = value self._studio_override_metadata = metadata self.had_studio_override = value is not NOT_SET - def update_project_values(self, value): + def update_project_value(self, value): value = self._check_update_value(value, "project override") value, metadata = self._prepare_value(value) self._project_override_value = value diff --git a/pype/settings/entities/input_entities.py b/pype/settings/entities/input_entities.py index 145c9ac811..f113cca0f5 100644 --- a/pype/settings/entities/input_entities.py +++ b/pype/settings/entities/input_entities.py @@ -69,12 +69,12 @@ class EndpointEntity(ItemEntity): self._default_value = value self.has_default_value = value is not NOT_SET - def update_studio_values(self, value): + def update_studio_value(self, value): value = self._check_update_value(value, "studio override") self._studio_override_value = value self.had_studio_override = bool(value is not NOT_SET) - def update_project_values(self, value): + def update_project_value(self, value): value = self._check_update_value(value, "project override") self._project_override_value = value self.had_project_override = bool(value is not NOT_SET) @@ -516,14 +516,14 @@ class RawJsonEntity(InputEntity): self._default_value = value self.default_metadata = metadata - def update_studio_values(self, value): + def update_studio_value(self, value): value = self._check_update_value(value, "studio override") self.had_studio_override = value is not NOT_SET value, metadata = self._prepare_value(value) self._studio_override_value = value self.studio_override_metadata = metadata - def update_project_values(self, value): + def update_project_value(self, value): value = self._check_update_value(value, "project override") self.had_project_override = value is not NOT_SET value, metadata = self._prepare_value(value) diff --git a/pype/settings/entities/item_entities.py b/pype/settings/entities/item_entities.py index f7b1b07e0e..20a7dbc513 100644 --- a/pype/settings/entities/item_entities.py +++ b/pype/settings/entities/item_entities.py @@ -156,11 +156,11 @@ class PathEntity(ItemEntity): def update_default_value(self, value): self.child_obj.update_default_value(value) - def update_project_values(self, value): - self.child_obj.update_project_values(value) + def update_project_value(self, value): + self.child_obj.update_project_value(value) - def update_studio_values(self, value): - self.child_obj.update_studio_values(value) + def update_studio_value(self, value): + self.child_obj.update_studio_value(value) def _discard_changes(self, *args): self.child_obj.discard_changes(*args) @@ -435,25 +435,25 @@ class ListStrictEntity(ItemEntity): for idx, item_value in enumerate(value): self.children[idx].update_default_value(item_value) - def update_studio_values(self, value): + def update_studio_value(self, value): value = self._check_update_value(value, "studio override") if value is NOT_SET: for child_obj in self.children: - child_obj.update_studio_values(value) + child_obj.update_studio_value(value) else: for idx, item_value in enumerate(value): - self.children[idx].update_studio_values(item_value) + self.children[idx].update_studio_value(item_value) - def update_project_values(self, value): + def update_project_value(self, value): value = self._check_update_value(value, "project override") if value is NOT_SET: for child_obj in self.children: - child_obj.update_project_values(value) + child_obj.update_project_value(value) else: for idx, item_value in enumerate(value): - self.children[idx].update_project_values(item_value) + self.children[idx].update_project_value(item_value) def reset_callbacks(self): super(ListStrictEntity, self).reset_callbacks() diff --git a/pype/settings/entities/list_entity.py b/pype/settings/entities/list_entity.py index 8fbbe7456d..9002fe9bf7 100644 --- a/pype/settings/entities/list_entity.py +++ b/pype/settings/entities/list_entity.py @@ -198,13 +198,13 @@ class ListEntity(EndpointEntity): child_obj.update_default_value(item) if self._override_state is OverrideState.PROJECT: if self.had_project_override: - child_obj.update_project_values(item) + child_obj.update_project_value(item) elif self.had_studio_override: - child_obj.update_studio_values(item) + child_obj.update_studio_value(item) elif self._override_state is OverrideState.STUDIO: if self.had_studio_override: - child_obj.update_studio_values(item) + child_obj.update_studio_value(item) for child_obj in self.children: child_obj.set_override_state(self._override_state) @@ -337,13 +337,13 @@ class ListEntity(EndpointEntity): child_obj.update_default_value(item) if self._override_state is OverrideState.PROJECT: if self.had_project_override: - child_obj.update_project_values(item) + child_obj.update_project_value(item) elif self.had_studio_override: - child_obj.update_studio_values(item) + child_obj.update_studio_value(item) elif self._override_state is OverrideState.STUDIO: if self.had_studio_override: - child_obj.update_studio_values(item) + child_obj.update_studio_value(item) child_obj.set_override_state(self._override_state) @@ -411,7 +411,7 @@ class ListEntity(EndpointEntity): child_obj = self._add_new_item() child_obj.update_default_value(item) if self._has_studio_override: - child_obj.update_studio_values(item) + child_obj.update_studio_value(item) child_obj.set_override_state(self._override_state) self._ignore_child_changes = False diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index 5fde2bc177..624e9a99ad 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -468,7 +468,7 @@ class SystemSettings(RootEntity): studio_overrides = get_studio_system_settings_overrides() for key, child_obj in self.non_gui_children.items(): value = studio_overrides.get(key, NOT_SET) - child_obj.update_studio_values(value) + child_obj.update_studio_value(value) def reset(self, new_state=None): """Discard changes and reset entit's values. @@ -600,7 +600,7 @@ class ProjectSettings(RootEntity): } for key, child_obj in self.non_gui_children.items(): value = project_override_value.get(key, NOT_SET) - child_obj.update_project_values(value) + child_obj.update_project_value(value) self.set_project_state() @@ -620,7 +620,7 @@ class ProjectSettings(RootEntity): for key, child_obj in self.non_gui_children.items(): value = studio_overrides.get(key, NOT_SET) - child_obj.update_studio_values(value) + child_obj.update_studio_value(value) if not self.project_name: return @@ -632,7 +632,7 @@ class ProjectSettings(RootEntity): } for key, child_obj in self.non_gui_children.items(): value = project_override_value.get(key, NOT_SET) - child_obj.update_project_values(value) + child_obj.update_project_value(value) def reset(self, new_state=None): """Discard changes and reset entit's values. From e20bfd267b3818aced62ba46e8dcb2f8313b2ad7 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 09:34:09 +0100 Subject: [PATCH 52/83] fix arguments of remove_from_project_overrides --- pype/settings/entities/dict_immutable_keys_entity.py | 4 ++-- pype/settings/entities/root_entities.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pype/settings/entities/dict_immutable_keys_entity.py b/pype/settings/entities/dict_immutable_keys_entity.py index 3fb6f563cb..3ffe0bdae5 100644 --- a/pype/settings/entities/dict_immutable_keys_entity.py +++ b/pype/settings/entities/dict_immutable_keys_entity.py @@ -503,13 +503,13 @@ class DictImmutableKeysEntity(ItemEntity): self._ignore_child_changes = False self.parent.on_child_change(self) - def _remove_from_project_override(self): + def _remove_from_project_override(self, on_change_trigger): if self._override_state is not OverrideState.PROJECT: return self._ignore_child_changes = True for child_obj in self.non_gui_children.values(): - child_obj.remove_from_project_override() + child_obj.remove_from_project_override(on_change_trigger) self._ignore_child_changes = False def reset_callbacks(self): diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index 624e9a99ad..dd895d9899 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -335,10 +335,10 @@ class RootEntity(BaseItemEntity): for child_obj in self.non_gui_children.values(): child_obj.add_to_project_override() - def _remove_from_project_override(self): + def _remove_from_project_override(self, on_change_trigger): """Implementation of abstract method only trigger children callback.""" for child_obj in self.non_gui_children.values(): - child_obj.remove_from_project_override() + child_obj.remove_from_project_override(on_change_trigger) def save(self): """Save values for current override state. From e449ef4b0e530168473aaa9813588a0b13da6312 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 09:42:54 +0100 Subject: [PATCH 53/83] immutable dict does not care about it's _has_*_overrides attribute --- .../entities/dict_immutable_keys_entity.py | 42 ++----------------- 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/pype/settings/entities/dict_immutable_keys_entity.py b/pype/settings/entities/dict_immutable_keys_entity.py index 3ffe0bdae5..642fde9685 100644 --- a/pype/settings/entities/dict_immutable_keys_entity.py +++ b/pype/settings/entities/dict_immutable_keys_entity.py @@ -246,24 +246,6 @@ class DictImmutableKeysEntity(ItemEntity): # Change has/had override states self._override_state = state - if state is OverrideState.NOT_DEFINED: - pass - - elif state is OverrideState.DEFAULTS: - self.has_default_value = self._default_value is not NOT_SET - - elif state is OverrideState.STUDIO: - self.had_studio_override = ( - self._studio_override_metadata is not NOT_SET - ) - self._has_studio_override = self.had_studio_override - - elif state is OverrideState.PROJECT: - self._has_studio_override = self.had_studio_override - self.had_project_override = ( - self._project_override_metadata is not NOT_SET - ) - self._has_project_override = self.had_project_override for child_obj in self.non_gui_children.values(): child_obj.set_override_state(state) @@ -282,19 +264,6 @@ class DictImmutableKeysEntity(ItemEntity): if self._metadata_are_modified: return True - if self.is_group or self.group_item: - if ( - self._override_state is OverrideState.PROJECT - and self._has_project_override != self.had_project_override - ): - return True - - elif ( - self._override_state is OverrideState.STUDIO - and self._has_studio_override != self.had_studio_override - ): - return True - return self._child_has_unsaved_changes @property @@ -306,9 +275,7 @@ class DictImmutableKeysEntity(ItemEntity): @property def has_studio_override(self): - if not self.is_group and not self.group_item: - return self._child_has_studio_override - return self._has_studio_override or self._child_has_studio_override + return self._child_has_studio_override @property def _child_has_studio_override(self): @@ -320,9 +287,7 @@ class DictImmutableKeysEntity(ItemEntity): @property def has_project_override(self): - if not self.is_group and not self.group_item: - return self._child_has_project_override - return self._has_project_override or self._child_has_project_override + return self._child_has_project_override @property def _child_has_project_override(self): @@ -419,6 +384,7 @@ class DictImmutableKeysEntity(ItemEntity): value = self._check_update_value(value, "studio override") value, metadata = self._prepare_value(value) self._studio_override_metadata = metadata + self.had_studio_override = metadata is not NOT_SET if value is NOT_SET: for child_obj in self.non_gui_children.values(): @@ -447,6 +413,7 @@ class DictImmutableKeysEntity(ItemEntity): value = self._check_update_value(value, "project override") value, metadata = self._prepare_value(value) self._project_override_metadata = metadata + self.had_project_override = metadata is not NOT_SET if value is NOT_SET: for child_obj in self.non_gui_children.values(): @@ -491,7 +458,6 @@ class DictImmutableKeysEntity(ItemEntity): for child_obj in self.non_gui_children.values(): child_obj.remove_from_studio_default(on_change_trigger) self._ignore_child_changes = False - self._has_studio_override = False def add_to_project_override(self): if self._override_state is not OverrideState.PROJECT: From 0dbbbba8186742ad6cb20ae21183cf4e578dccd1 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 10:06:10 +0100 Subject: [PATCH 54/83] removed gui schemas from setttings tool --- .../projects_schema/schema_main.json | 76 -- .../projects_schema/schema_plugins.json | 54 -- .../schema_project_celaction.json | 62 -- .../schema_project_ftrack.json | 663 ------------------ .../schema_project_global.json | 33 - .../schema_project_harmony.json | 36 - .../projects_schema/schema_project_hiero.json | 172 ----- .../projects_schema/schema_project_maya.json | 29 - .../projects_schema/schema_project_nuke.json | 193 ----- .../schema_project_resolve.json | 124 ---- .../schema_project_standalonepublisher.json | 93 --- .../schema_project_syncserver.json | 76 -- .../schema_project_unreal.json | 27 - .../schemas/schema_anatomy_attributes.json | 79 --- .../schemas/schema_anatomy_imageio.json | 353 ---------- .../schemas/schema_anatomy_templates.json | 135 ---- .../schemas/schema_global_publish.json | 407 ----------- .../schemas/schema_global_tools.json | 77 -- .../schemas/schema_maya_capture.json | 595 ---------------- .../schemas/schema_maya_load.json | 156 ----- .../schemas/schema_maya_publish.json | 214 ------ .../schemas/schema_publish_gui_filter.json | 10 - .../schemas/schema_workfile_build.json | 97 --- .../schemas/template_color.json | 30 - 24 files changed, 3791 deletions(-) delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_main.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_plugins.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_celaction.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_ftrack.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_global.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_harmony.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_hiero.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_maya.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_nuke.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_resolve.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_standalonepublisher.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_syncserver.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_unreal.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_attributes.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_imageio.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_templates.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_global_publish.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_global_tools.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_capture.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_load.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_publish.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_publish_gui_filter.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_workfile_build.json delete mode 100644 pype/tools/settings/settings/gui_schemas/projects_schema/schemas/template_color.json diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_main.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_main.json deleted file mode 100644 index 73266a9e79..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_main.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "key": "project", - "type": "dict", - "children": [ - { - "type": "anatomy", - "key": "project_anatomy", - "children": [ - { - "type": "anatomy_roots", - "key": "roots", - "label": "Roots", - "is_file": true - }, - { - "type": "schema", - "name": "schema_anatomy_templates" - }, - { - "type": "schema", - "name": "schema_anatomy_attributes" - }, - { - "type": "schema", - "name": "schema_anatomy_imageio" - } - ] - }, - { - "type": "dict", - "key": "project_settings", - "children": [ - { - "type": "schema", - "name": "schema_project_global" - }, - { - "type": "schema", - "name": "schema_project_ftrack" - }, - { - "type": "schema", - "name": "schema_project_maya" - }, - { - "type": "schema", - "name": "schema_project_nuke" - }, - { - "type": "schema", - "name": "schema_project_hiero" - }, - { - "type": "schema", - "name": "schema_project_harmony" - }, - { - "type": "schema", - "name": "schema_project_celaction" - }, - { - "type": "schema", - "name": "schema_project_resolve" - }, - { - "type": "schema", - "name": "schema_project_standalonepublisher" - }, - { - "type": "schema", - "name": "schema_project_unreal" - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_plugins.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_plugins.json deleted file mode 100644 index ce90ceb881..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_plugins.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "plugins", - "label": "Plugins", - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "standalonepublisher", - "label": "Standalone Publisher", - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "publish", - "label": "Publish plugins", - "is_file": true, - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "ExtractThumbnailSP", - "label": "ExtractThumbnailSP", - "is_group": true, - "children": [ - { - "type": "dict", - "collapsable": false, - "key": "ffmpeg_args", - "label": "ffmpeg_args", - "children": [ - { - "type": "list", - "object_type": "text", - "key": "input", - "label": "input" - }, - { - "type": "list", - "object_type": "text", - "key": "output", - "label": "output" - } - ] - } - ] - } - ] - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_celaction.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_celaction.json deleted file mode 100644 index 86d6141c4a..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_celaction.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "celaction", - "label": "CelAction", - "is_file": true, - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "publish", - "label": "Publish plugins", - "children": [ - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "ExtractCelactionDeadline", - "label": "ExtractCelactionDeadline", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "text", - "key": "deadline_department", - "label": "Deadline apartment" - }, - { - "type": "number", - "key": "deadline_priority", - "label": "Deadline priority" - }, - { - "type": "text", - "key": "deadline_pool", - "label": "Deadline pool" - }, - { - "type": "text", - "key": "deadline_pool_secondary", - "label": "Deadline pool (secondary)" - }, - { - "type": "text", - "key": "deadline_group", - "label": "Deadline Group" - }, - { - "type": "number", - "key": "deadline_chunk_size", - "label": "Deadline Chunk size" - } - ] - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_ftrack.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_ftrack.json deleted file mode 100644 index 508b8e870d..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_ftrack.json +++ /dev/null @@ -1,663 +0,0 @@ -{ - "type": "dict", - "key": "ftrack", - "label": "Ftrack", - "collapsable": true, - "checkbox_key": "enabled", - "is_file": true, - "children": [ - { - "type": "splitter" - }, - { - "type": "label", - "label": "Additional Ftrack paths" - }, - { - "type": "list", - "key": "ftrack_actions_path", - "label": "Action paths", - "object_type": "text" - }, - { - "type": "list", - "key": "ftrack_events_path", - "label": "Event paths", - "object_type": "text" - }, - { - "type": "splitter" - }, - { - "type": "dict", - "key": "events", - "label": "Server Actions/Events", - "children": [ - { - "type": "dict", - "key": "sync_to_avalon", - "label": "Sync to avalon", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Allow name and hierarchy change only if following statuses are on all children tasks" - }, - { - "type": "list", - "key": "statuses_name_change", - "label": "Statuses", - "object_type": { - "type": "text", - "multiline": false - } - } - ] - }, - { - "type": "dict", - "key": "sync_hier_entity_attributes", - "label": "Sync Hierarchical and Entity Attributes", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "interest_entity_types", - "label": "Entity types of interest", - "object_type": { - "type": "text", - "multiline": false - } - }, - { - "type": "list", - "key": "interest_attributes", - "label": "Attributes to sync", - "object_type": { - "type": "text", - "multiline": false - } - }, - { - "type": "separator" - }, - { - "type": "boolean", - "key": "action_enabled", - "label": "Enable Action" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles for action", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "clone_review_session", - "label": "Clone Review Session", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles for action", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "thumbnail_updates", - "label": "Update Hierarchy thumbnails", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Push thumbnail from version, up through multiple hierarchy levels." - }, - { - "type": "number", - "key": "levels", - "label": "Levels" - } - ] - }, - { - "type": "dict", - "key": "user_assignment", - "label": "Run script on user assignments", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - } - ] - }, - { - "type": "dict", - "key": "status_update", - "label": "Update status on task action", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "key": "mapping", - "type": "dict-modifiable", - "object_type": { - "type": "list", - "object_type": "text" - } - } - ] - }, - { - "type": "dict", - "key": "status_task_to_parent", - "label": "Sync status from Task to Parent", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "List of parent object types where this is triggered (\"Shot\", \"Asset Build\", etc.). Skipped if list is empty." - }, - { - "type": "list", - "object_type": "text", - "key": "parent_object_types", - "label": "Object types" - }, - { - "key": "parent_status_match_all_task_statuses", - "type": "dict-modifiable", - "label": "Change parent if all tasks match", - "object_type": { - "type": "list", - "object_type": "text" - } - }, - { - "type": "list", - "key": "parent_status_by_task_status", - "label": "Change parent status if a single task matches", - "use_label_wrap": true, - "object_type": { - "type": "dict", - "children": [ - { - "type": "text", - "label": "New parent status", - "key": "new_status" - }, - { - "type": "separator" - }, - { - "type": "list", - "label": "Task status", - "key": "task_statuses", - "object_type": "text" - } - ] - } - } - ] - }, - { - "type": "dict", - "key": "status_task_to_version", - "label": "Sync status from Task to Version", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "dict-modifiable", - "key": "mapping", - "object_type": - { - "type": "list", - "object_type": "text" - } - }, - { - "type": "label", - "label": "Limit status changes to entered asset types. Limitation is ignored if nothing is entered." - }, - { - "type": "list", - "key": "asset_types_filter", - "label": "Asset types (short)", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "status_version_to_task", - "label": "Sync status from Version to Task", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Change Task status based on a changed Version status.
Version's new status on the left will trigger a change of a task status to the first available from the list on right.
- if no status from the list is available it will use the same status as the version." - }, - { - "type": "dict-modifiable", - "key": "mapping", - "object_type": { - "type": "list", - "object_type": "text" - } - }, - { - "type": "separator" - }, - { - "type": "label", - "label": "Disable event if status was changed on specific Asset type." - }, - { - "type": "list", - "label": "Asset types (short)", - "key": "asset_types_to_skip", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "first_version_status", - "label": "Set status on first created version", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "text", - "key": "status", - "label": "Status" - } - ] - }, - { - "type": "dict", - "key": "next_task_update", - "label": "Update status on next task", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Change status on next task by task types order when task status state changed to \"Done\". All tasks with same Task type must be \"Done\"." - }, - { - "type": "label", - "label": "Mapping of next task status changes From -> To." - }, - { - "type": "dict-modifiable", - "key": "mapping", - "object_type": { - "type": "text" - } - }, - { - "type": "separator" - }, - { - "type": "label", - "label": "Status names that are ignored on \"Done\" check (e.g. \"Omitted\")." - }, - { - "type": "list", - "key": "ignored_statuses", - "object_type": "text" - }, - { - "type": "separator" - }, - { - "type": "label", - "label": "Allow to break rule that all tasks with same Task type must be \"Done\" and change statuses with same type tasks ordered by name." - }, - { - "label": "Name sorting", - "type": "boolean", - "key": "name_sorting" - } - ] - } - ] - }, - { - "type": "dict", - "key": "user_handlers", - "label": "User Actions/Events", - "children": [ - { - "type": "dict", - "key": "application_launch_statuses", - "label": "Application - Status change on launch", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Do not change status if current status is:" - }, - { - "type": "list", - "key": "ignored_statuses", - "object_type": "text" - }, - { - "type": "label", - "label": "Change task's status to left side if current task status is in list on right side." - }, - { - "type": "dict-modifiable", - "key": "status_change", - "object_type": { - "type": "list", - "object_type": "text" - } - } - ] - }, - { - "type": "dict", - "key": "create_update_attributes", - "label": "Create/Update Avalon Attributes", - "children": [ - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "prepare_project", - "label": "Prepare Project", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "clean_hierarchical_attr", - "label": "Clean hierarchical custom attributes", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "delete_asset_subset", - "label": "Delete Asset/Subsets", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "delete_old_versions", - "label": "Delete old versions", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "delivery_action", - "label": "Delivery", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "store_thubmnail_to_avalon", - "label": "Store Thumbnails to avalon", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "job_killer", - "label": "Job Killer", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "sync_to_avalon_local", - "label": "Sync to avalon (local) - For development", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - }, - { - "type": "dict", - "key": "seed_project", - "label": "Seed Debug Project", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "role_list", - "label": "Roles", - "object_type": "text" - } - ] - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "publish", - "label": "Publish plugins", - "is_file": true, - "children": [ - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "IntegrateFtrackNote", - "label": "IntegrateFtrackNote", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "text", - "key": "note_with_intent_template", - "label": "Note with intent template" - }, - { - "type": "list", - "object_type": "text", - "key": "note_labels", - "label": "Note labels" - } - ] - }, - - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "ValidateFtrackAttributes", - "label": "ValidateFtrackAttributes", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "raw-json", - "key": "ftrack_custom_attributes", - "label": "Custom attributes to validate" - } - ] - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_global.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_global.json deleted file mode 100644 index ab9b56115d..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_global.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "global", - "label": "Global", - "is_file": true, - "children": [ - { - "type": "schema", - "name": "schema_global_publish" - }, - { - "type": "schema", - "name": "schema_global_tools" - }, - - { - "type": "collapsible-wrap", - "label": "Project Folder Structure", - "children": [ - { - "type": "raw-json", - "key": "project_folder_structure" - } - ] - }, - - { - "type": "schema", - "name": "schema_project_syncserver" - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_harmony.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_harmony.json deleted file mode 100644 index 92ad39ac2c..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_harmony.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "harmony", - "label": "Harmony", - "is_file": true, - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "publish", - "label": "Publish plugins", - "children": [] - }, - { - "type": "dict", - "collapsable": true, - "key": "general", - "label": "General", - "children": [ - { - "type": "list", - "key": "skip_resolution_check", - "object_type": "text", - "label": "Skip Resolution Check for Tasks" - }, - { - "type": "list", - "key": "skip_timelines_check", - "object_type": "text", - "label": "Skip Timeliene Check for Tasks" - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_hiero.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_hiero.json deleted file mode 100644 index b6276ccf9e..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_hiero.json +++ /dev/null @@ -1,172 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "hiero", - "label": "Hiero", - "is_file": true, - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "create", - "label": "Create plugins", - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "CreateShotClip", - "label": "Create Shot Clip", - "is_group": true, - "children": [ - { - "type": "collapsible-wrap", - "label": "Shot Hierarchy And Rename Settings", - "collapsable": false, - "children": [ - { - "type": "text", - "key": "hierarchy", - "label": "Shot parent hierarchy" - }, - { - "type": "boolean", - "key": "clipRename", - "label": "Rename clips" - }, - { - "type": "text", - "key": "clipName", - "label": "Clip name template" - }, - { - "type": "number", - "key": "countFrom", - "label": "Count sequence from" - }, - { - "type": "number", - "key": "countSteps", - "label": "Stepping number" - } - ] - }, - { - "type": "collapsible-wrap", - "label": "Shot Template Keywords", - "collapsable": false, - "children": [ - { - "type": "text", - "key": "folder", - "label": "{folder}" - }, - { - "type": "text", - "key": "episode", - "label": "{episode}" - }, - { - "type": "text", - "key": "sequence", - "label": "{sequence}" - }, - { - "type": "text", - "key": "track", - "label": "{track}" - }, - { - "type": "text", - "key": "shot", - "label": "{shot}" - } - ] - }, - { - "type": "collapsible-wrap", - "label": "Vertical Synchronization Of Attributes", - "collapsable": false, - "children": [ - { - "type": "boolean", - "key": "vSyncOn", - "label": "Enable Vertical Sync" - } - ] - }, - { - "type": "collapsible-wrap", - "label": "Shot Attributes", - "collapsable": false, - "children": [ - { - "type": "number", - "key": "workfileFrameStart", - "label": "Workfiles Start Frame" - }, - { - "type": "number", - "key": "handleStart", - "label": "Handle start (head)" - }, - { - "type": "number", - "key": "handleEnd", - "label": "Handle end (tail)" - } - ] - } - ] - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "publish", - "label": "Publish plugins", - "children": [ - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "CollectInstanceVersion", - "label": "Collect Instance Version", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "ExtractReviewCutUpVideo", - "label": "Extract Review Cut Up Video", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "object_type": "text", - "key": "tags_addition", - "label": "Tags addition" - } - ] - } - ] - }, - { - "type": "schema", - "name": "schema_publish_gui_filter" - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_maya.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_maya.json deleted file mode 100644 index 069ae3c977..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_maya.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "maya", - "label": "Maya", - "is_file": true, - "children": [ - { - "type": "schema", - "name": "schema_maya_capture" - }, - { - "type": "schema", - "name": "schema_maya_publish" - }, - { - "type": "schema", - "name": "schema_maya_load" - }, - { - "type": "schema", - "name": "schema_workfile_build" - }, - { - "type": "schema", - "name": "schema_publish_gui_filter" - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_nuke.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_nuke.json deleted file mode 100644 index 7a6960bcbd..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_nuke.json +++ /dev/null @@ -1,193 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "nuke", - "label": "Nuke", - "is_file": true, - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "create", - "label": "Create plugins", - "children": [ - { - "type": "dict", - "collapsable": false, - "key": "CreateWriteRender", - "label": "CreateWriteRender", - "is_group": true, - "children": [ - { - "type": "text", - "key": "fpath_template", - "label": "Path template" - } - ] - }, - { - "type": "dict", - "collapsable": false, - "key": "CreateWritePrerender", - "label": "CreateWritePrerender", - "is_group": true, - "children": [ - { - "type": "text", - "key": "fpath_template", - "label": "Path template" - } - ] - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "publish", - "label": "Publish plugins", - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "PreCollectNukeInstances", - "label": "PreCollectNukeInstances", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "sync_workfile_version", - "label": "Sync Version from workfile" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "ExtractThumbnail", - "label": "ExtractThumbnail", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "raw-json", - "key": "nodes", - "label": "Nodes" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "ValidateKnobs", - "label": "ValidateKnobs", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "raw-json", - "key": "knobs", - "label": "Knobs" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "ExtractReviewDataLut", - "label": "ExtractReviewDataLut", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "ExtractReviewDataMov", - "label": "ExtractReviewDataMov", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "viewer_lut_raw", - "label": "Viewer LUT raw" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "ExtractSlateFrame", - "label": "ExtractSlateFrame", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "viewer_lut_raw", - "label": "Viewer LUT raw" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "NukeSubmitDeadline", - "label": "NukeSubmitDeadline", - "is_group": true, - "children": [ - { - "type": "number", - "key": "deadline_priority", - "label": "deadline_priority" - }, - { - "type": "text", - "key": "deadline_pool", - "label": "deadline_pool" - }, - { - "type": "text", - "key": "deadline_pool_secondary", - "label": "deadline_pool_secondary" - }, - { - "type": "number", - "key": "deadline_chunk_size", - "label": "deadline_chunk_size" - } - ] - } - ] - }, - { - "type": "schema", - "name": "schema_workfile_build" - }, - { - "type": "schema", - "name": "schema_publish_gui_filter" - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_resolve.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_resolve.json deleted file mode 100644 index fb9b9b7a0a..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_resolve.json +++ /dev/null @@ -1,124 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "resolve", - "label": "DaVinci Resolve", - "is_file": true, - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "create", - "label": "Creator plugins", - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "CreateShotClip", - "label": "Create Shot Clip", - "is_group": true, - "children": [ - { - "type": "collapsible-wrap", - "label": "Shot Hierarchy And Rename Settings", - "collapsable": false, - "children": [ - { - "type": "text", - "key": "hierarchy", - "label": "Shot parent hierarchy" - }, - { - "type": "boolean", - "key": "clipRename", - "label": "Rename clips" - }, - { - "type": "text", - "key": "clipName", - "label": "Clip name template" - }, - { - "type": "number", - "key": "countFrom", - "label": "Count sequence from" - }, - { - "type": "number", - "key": "countSteps", - "label": "Stepping number" - } - ] - }, - { - "type": "collapsible-wrap", - "label": "Shot Template Keywords", - "collapsable": false, - "children": [ - { - "type": "text", - "key": "folder", - "label": "{folder}" - }, - { - "type": "text", - "key": "episode", - "label": "{episode}" - }, - { - "type": "text", - "key": "sequence", - "label": "{sequence}" - }, - { - "type": "text", - "key": "track", - "label": "{track}" - }, - { - "type": "text", - "key": "shot", - "label": "{shot}" - } - ] - }, - { - "type": "collapsible-wrap", - "label": "Vertical Synchronization Of Attributes", - "collapsable": false, - "children": [ - { - "type": "boolean", - "key": "vSyncOn", - "label": "Enable Vertical Sync" - } - ] - }, - { - "type": "collapsible-wrap", - "label": "Shot Attributes", - "collapsable": false, - "children": [ - { - "type": "number", - "key": "workfileFrameStart", - "label": "Workfiles Start Frame" - }, - { - "type": "number", - "key": "handleStart", - "label": "Handle start (head)" - }, - { - "type": "number", - "key": "handleEnd", - "label": "Handle end (tail)" - } - ] - } - ] - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_standalonepublisher.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_standalonepublisher.json deleted file mode 100644 index 40b27f766f..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_standalonepublisher.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "standalonepublisher", - "label": "Standalone Publisher", - "is_file": true, - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "publish", - "label": "Publish plugins", - "is_file": true, - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "ExtractThumbnailSP", - "label": "ExtractThumbnailSP", - "is_group": true, - "children": [ - { - "type": "dict", - "collapsable": false, - "key": "ffmpeg_args", - "label": "ffmpeg_args", - "children": [ - { - "type": "list", - "object_type": "text", - "key": "input", - "label": "input" - }, - { - "type": "list", - "object_type": "text", - "key": "output", - "label": "output" - } - ] - } - ] - } - ] - }, - { - "type": "dict-modifiable", - "collapsable": true, - "key": "create", - "label": "Creator plugins", - "collapsable_key": true, - "is_file": true, - "object_type": { - "type": "dict", - "children": [ - { - "type": "text", - "key": "name", - "label": "Name" - }, - { - "type": "text", - "key": "label", - "label": "Label" - }, - { - "type": "text", - "key": "family", - "label": "Family" - }, - { - "type": "text", - "key": "icon", - "label": "Icon" - }, - { - "type": "list", - "key": "defaults", - "label": "Defaults", - "object_type": { - "type": "text" - } - }, - { - "type": "text", - "key": "help", - "label": "Help" - } - ] - } - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_syncserver.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_syncserver.json deleted file mode 100644 index 396e4ca2dc..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_syncserver.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "type": "dict", - "key": "sync_server", - "label": "Sync Server (currently unused)", - "collapsable": true, - "checkbox_key": "enabled", - "is_file": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "dict", - "key": "config", - "label": "Config", - "collapsable": true, - "children": [ - - { - "type": "text", - "key": "local_id", - "label": "Local ID" - }, - { - "type": "text", - "key": "retry_cnt", - "label": "Retry Count" - }, - { - "type": "text", - "key": "loop_delay", - "label": "Loop Delay" - }, - { - "type": "text", - "key": "active_site", - "label": "Active Site" - }, - { - "type": "text", - "key": "remote_site", - "label": "Remote Site" - } - ] - }, { - "type": "dict-modifiable", - "collapsable": true, - "key": "sites", - "label": "Sites", - "collapsable_key": false, - "is_file": true, - "object_type": - { - "type": "dict", - "children": [ - { - "type": "text", - "key": "provider", - "label": "Provider" - }, - { - "type": "text", - "key": "credentials_url", - "label": "Credentials url" - }, - { - "type": "text", - "key": "root", - "label": "Root" - }] - } - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_unreal.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_unreal.json deleted file mode 100644 index 392289296a..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schema_project_unreal.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "unreal", - "label": "Unreal Engine", - "is_file": true, - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "project_setup", - "label": "Project Setup", - "children": [ - { - "type": "boolean", - "key": "dev_mode", - "label": "Dev mode" - }, - { - "type": "boolean", - "key": "install_unreal_python_engine", - "label": "Install unreal python engine" - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_attributes.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_attributes.json deleted file mode 100644 index b045ef978b..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_attributes.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "attributes", - "label": "Attributes", - "is_file": true, - "children": [ - { - "type": "number", - "key": "fps", - "label": "Frame Rate" - }, - { - "type": "number", - "key": "frameStart", - "label": "Frame Start" - }, - { - "type": "number", - "key": "frameEnd", - "label": "Frame End" - }, - { - "type": "number", - "key": "clipIn", - "label": "Clip In" - }, - { - "type": "number", - "key": "clipOut", - "label": "Clip Out" - }, - { - "type": "number", - "key": "handleStart", - "label": "Handle Start" - }, - { - "type": "number", - "key": "handleEnd", - "label": "Handle End" - }, - { - "type": "number", - "key": "resolutionWidth", - "label": "Resolution Width" - }, - { - "type": "number", - "key": "resolutionHeight", - "label": "Resolution Height" - }, - { - "type": "number", - "key": "pixelAspect", - "label": "Pixel Aspect Ratio" - }, - { - "type": "enum", - "key": "applications", - "label": "Applications", - "multiselection": true, - "enum_items": [ - { "maya_2020": "Maya 2020" }, - { "nuke_12.2": "Nuke 12.2" }, - { "hiero_12.2": "Hiero 12.2" }, - { "houdini_18": "Houdini 18" }, - { "blender_2.91": "Blender 2.91" }, - { "aftereffects_2021": "After Effects 2021" } - ] - }, - { - "type": "dict-modifiable", - "key": "task_short_names", - "label": "Task short names (by Task type)", - "object_type": "text" - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_imageio.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_imageio.json deleted file mode 100644 index 0032e3de06..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_imageio.json +++ /dev/null @@ -1,353 +0,0 @@ -{ - "type": "dict", - "key": "imageio", - "label": "Color Management and Output Formats", - "is_file": true, - "children": [ - { - "key": "hiero", - "type": "dict", - "label": "Hiero", - "children": [ - { - "key": "workfile", - "type": "dict", - "label": "Workfile", - "collapsable": false, - "children": [ - { - "type": "form", - "children": [ - { - "type": "enum", - "key": "ocioConfigName", - "label": "OpenColorIO Config", - "enum_items": [ - { - "nuke-default": "nuke-default" - }, - { - "aces_1.0.3": "aces_1.0.3" - }, - { - "aces_1.1": "aces_1.1" - }, - { - "custom": "custom" - } - ] - }, - { - "type": "path-widget", - "key": "ocioconfigpath", - "label": "Custom OCIO path", - "multiplatform": true, - "multipath": true - }, - { - "type": "text", - "key": "workingSpace", - "label": "Working Space" - }, - { - "type": "text", - "key": "sixteenBitLut", - "label": "16 Bit Files" - }, - { - "type": "text", - "key": "eightBitLut", - "label": "8 Bit Files" - }, - { - "type": "text", - "key": "floatLut", - "label": "Floating Point Files" - }, - { - "type": "text", - "key": "logLut", - "label": "Log Files" - }, - { - "type": "text", - "key": "viewerLut", - "label": "Viewer" - }, - { - "type": "text", - "key": "thumbnailLut", - "label": "Thumbnails" - } - ] - } - ] - }, - { - "key": "regexInputs", - "type": "dict", - "label": "Colorspace on Inputs by regex detection", - "collapsable": true, - "children": [ - { - "type": "list", - "key": "inputs", - "object_type": { - "type": "dict", - "children": [ - { - "type": "text", - "key": "regex", - "label": "Regex" - }, - { - "type": "text", - "key": "colorspace", - "label": "Colorspace" - } - ] - } - } - ] - } - ] - }, - { - "key": "nuke", - "type": "dict", - "label": "Nuke", - "children": [ - { - "key": "workfile", - "type": "dict", - "label": "Workfile", - "collapsable": false, - "is_group": true, - "children": [ - { - "type": "form", - "children": [ - { - "type": "enum", - "key": "colorManagement", - "label": "color management", - "enum_items": [ - { - "Nuke": "Nuke" - }, - { - "OCIO": "OCIO" - } - ] - }, - { - "type": "enum", - "key": "OCIO_config", - "label": "OpenColorIO Config", - "enum_items": [ - { - "nuke-default": "nuke-default" - }, - { - "spi-vfx": "spi-vfx" - }, - { - "spi-anim": "spi-anim" - }, - { - "aces_1.0.3": "aces_0.1.1" - }, - { - "aces_1.0.3": "aces_0.7.1" - }, - { - "aces_1.0.3": "aces_1.0.1" - }, - { - "aces_1.0.3": "aces_1.0.3" - }, - { - "aces_1.1": "aces_1.1" - }, - { - "custom": "custom" - } - ] - }, - { - "type": "path-widget", - "key": "customOCIOConfigPath", - "label": "Custom OCIO config path", - "multiplatform": true, - "multipath": true - }, - { - "type": "text", - "key": "workingSpaceLUT", - "label": "Working Space" - }, - { - "type": "text", - "key": "monitorLut", - "label": "monitor" - }, - { - "type": "text", - "key": "int8Lut", - "label": "8-bit files" - }, - { - "type": "text", - "key": "int16Lut", - "label": "16-bit files" - }, - { - "type": "text", - "key": "logLut", - "label": "log files" - }, - { - "type": "text", - "key": "floatLut", - "label": "float files" - } - ] - } - ] - }, - { - "key": "nodes", - "type": "dict", - "label": "Nodes", - "collapsable": true, - "is_group": true, - "children": [ - { - "key": "requiredNodes", - "type": "list", - "label": "Required Nodes", - "object_type": { - "type": "dict", - "children": [ - { - "type": "list", - "key": "plugins", - "label": "Used in plugins", - "object_type": { - "type": "text", - "key": "pluginClass", - "label": "Plugin Class" - } - }, - { - "type": "text", - "key": "nukeNodeClass", - "label": "Nuke Node Class" - }, - { - "type": "splitter" - }, - { - "key": "knobs", - "label": "Knobs", - "type": "list", - "object_type": { - "type": "dict", - "children": [ - { - "type": "text", - "key": "name", - "label": "Name" - }, - { - "type": "text", - "key": "value", - "label": "Value" - } - ] - } - } - ] - } - }, - { - "type": "list", - "key": "customNodes", - "label": "Custom Nodes", - "object_type": { - "type": "dict", - "children": [ - { - "type": "list", - "key": "plugins", - "label": "Used in plugins", - "object_type": { - "type": "text", - "key": "pluginClass", - "label": "Plugin Class" - } - }, - { - "type": "text", - "key": "nukeNodeClass", - "label": "Nuke Node Class" - }, - { - "type": "splitter" - }, - { - "key": "knobs", - "label": "Knobs", - "type": "list", - "object_type": { - "type": "dict", - "children": [ - { - "type": "text", - "key": "name", - "label": "Name" - }, - { - "type": "text", - "key": "value", - "label": "Value" - } - ] - } - } - ] - } - } - ] - }, - { - "key": "regexInputs", - "type": "dict", - "label": "Colorspace on Inputs by regex detection", - "collapsable": true, - "children": [ - { - "type": "list", - "key": "inputs", - "object_type": { - "type": "dict", - "children": [ - { - "type": "text", - "key": "regex", - "label": "Regex" - }, - { - "type": "text", - "key": "colorspace", - "label": "Colorspace" - } - ] - } - } - ] - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_templates.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_templates.json deleted file mode 100644 index 1f545f14be..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_anatomy_templates.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "templates", - "label": "Templates", - "collapsable_key": true, - "is_file": true, - "children": [ - { - "type": "number", - "key": "version_padding", - "label": "Version Padding" - }, - { - "type": "text", - "key": "version", - "label": "Version" - }, - { - "type": "number", - "key": "frame_padding", - "label": "Frame Padding" - }, - { - "type": "text", - "key": "frame", - "label": "Frame" - }, - { - "type": "dict", - "key": "work", - "label": "Work", - "children": [ - { - "type": "text", - "key": "folder", - "label": "Folder" - }, - { - "type": "text", - "key": "file", - "label": "File" - }, - { - "type": "text", - "key": "path", - "label": "Path" - } - ] - }, - { - "type": "dict", - "key": "render", - "label": "Render", - "children": [ - { - "type": "text", - "key": "folder", - "label": "Folder" - }, - { - "type": "text", - "key": "file", - "label": "File" - }, - { - "type": "text", - "key": "path", - "label": "Path" - } - ] - }, - { - "type": "dict", - "key": "publish", - "label": "Publish", - "children": [ - { - "type": "text", - "key": "folder", - "label": "Folder" - }, - { - "type": "text", - "key": "file", - "label": "File" - }, - { - "type": "text", - "key": "path", - "label": "Path" - }, - { - "type": "text", - "key": "thumbnail", - "label": "Thumbnail" - } - ] - }, - { - "type": "dict", - "key": "master", - "label": "Master", - "children": [ - { - "type": "text", - "key": "folder", - "label": "Folder" - }, - { - "type": "text", - "key": "file", - "label": "File" - }, - { - "type": "text", - "key": "path", - "label": "Path" - } - ] - }, - { - "type": "dict-modifiable", - "key": "delivery", - "label": "Delivery", - "object_type": "text" - }, - { - "type": "dict-modifiable", - "key": "other", - "label": "Other", - "object_type": "text" - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_global_publish.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_global_publish.json deleted file mode 100644 index 5d17830b92..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_global_publish.json +++ /dev/null @@ -1,407 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "publish", - "label": "Publish plugins", - "children": [ - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "IntegrateMasterVersion", - "label": "IntegrateMasterVersion", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "checkbox_key": "enabled", - "key": "ExtractJpegEXR", - "label": "ExtractJpegEXR", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "dict", - "key": "ffmpeg_args", - "children": [ - { - "type": "list", - "object_type": "text", - "key": "input", - "label": "FFmpeg input arguments" - }, - { - "type": "list", - "object_type": "text", - "key": "output", - "label": "FFmpeg output arguments" - } - ] - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "ExtractReview", - "label": "ExtractReview", - "checkbox_key": "enabled", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "list", - "key": "profiles", - "label": "Profiles", - "object_type": { - "type": "dict", - "children": [ - { - "key": "families", - "label": "Families", - "type": "list", - "object_type": "text" - }, - { - "key": "hosts", - "label": "Hosts", - "type": "list", - "object_type": "text" - }, - { - "type": "splitter" - }, - { - "key": "outputs", - "label": "Output Definitions", - "type": "dict-modifiable", - "highlight_content": true, - "object_type": { - "type": "dict", - "children": [ - { - "key": "ext", - "label": "Output extension", - "type": "text" - }, - { - "key": "tags", - "label": "Tags", - "type": "enum", - "multiselection": true, - "enum_items": [ - { - "burnin": "Add burnins" - }, - { - "ftrackreview": "Add to Ftrack" - }, - { - "delete": "Delete output" - }, - { - "slate-frame": "Add slate frame" - }, - { - "no-hnadles": "Skip handle frames" - } - ] - }, - { - "key": "ffmpeg_args", - "label": "FFmpeg arguments", - "type": "dict", - "highlight_content": true, - "children": [ - { - "key": "video_filters", - "label": "Video filters", - "type": "list", - "object_type": "text" - }, - { - "type": "splitter" - }, - { - "key": "audio_filters", - "label": "Audio filters", - "type": "list", - "object_type": "text" - }, - { - "type": "splitter" - }, - { - "key": "input", - "label": "Input arguments", - "type": "list", - "object_type": "text" - }, - { - "type": "splitter" - }, - { - "key": "output", - "label": "Output arguments", - "type": "list", - "object_type": "text" - } - ] - }, - { - "key": "filter", - "label": "Additional output filtering", - "type": "dict", - "highlight_content": true, - "children": [ - { - "key": "families", - "label": "Families", - "type": "list", - "object_type": "text" - } - ] - } - ] - } - } - ] - } - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "ExtractBurnin", - "label": "ExtractBurnin", - "checkbox_key": "enabled", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "dict", - "collapsable": true, - "key": "options", - "label": "Burnin formating options", - "children": [ - { - "type": "number", - "key": "font_size", - "label": "Font size" - }, - { - "type": "number", - "key": "opacity", - "label": "Font opacity" - }, - { - "type": "number", - "key": "bg_opacity", - "label": "Background opacity" - }, - { - "type": "number", - "key": "x_offset", - "label": "X Offset" - }, - { - "type": "number", - "key": "y_offset", - "label": "Y Offset" - }, - { - "type": "number", - "key": "bg_padding", - "label": "Padding aroung text" - }, - { - "type": "splitter" - } - ] - }, - - { - "type": "list", - "key": "profiles", - "label": "Profiles", - "object_type": { - "type": "dict", - "children": [ - { - "key": "families", - "label": "Families", - "type": "list", - "object_type": "text" - }, - { - "key": "hosts", - "label": "Hosts", - "type": "list", - "object_type": "text" - }, - { - "type": "splitter" - }, - { - "key": "burnins", - "label": "Burnins", - "type": "dict-modifiable", - "highlight_content": true, - "collapsable": false, - "object_type": { - "type": "dict", - "children": [ - { - "key": "TOP_LEFT", - "label": "Top Left", - "type": "text" - }, - { - "key": "TOP_CENTERED", - "label": "Top Centered", - "type": "text" - }, - { - "key": "TOP_RIGHT", - "label": "top Right", - "type": "text" - }, - { - "key": "BOTTOM_LEFT", - "label": "Bottom Left", - "type": "text" - }, - { - "key": "BOTTOM_CENTERED", - "label": "Bottom Centered", - "type": "text" - }, - { - "key": "BOTTOM_RIGHT", - "label": "BottomRight", - "type": "text" - } - ] - } - } - ] - } - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "IntegrateAssetNew", - "label": "IntegrateAssetNew", - "is_group": true, - "children": [ - { - "type": "raw-json", - "key": "template_name_profiles", - "label": "template_name_profiles" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "ProcessSubmittedJobOnFarm", - "label": "ProcessSubmittedJobOnFarm", - "checkbox_key": "enabled", - "is_group": true, - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "text", - "key": "deadline_department", - "label": "Deadline department" - }, - { - "type": "text", - "key": "deadline_pool", - "label": "Deadline Pool" - }, - { - "type": "text", - "key": "deadline_group", - "label": "Deadline Group" - }, - { - "type": "number", - "key": "deadline_chunk_size", - "label": "Deadline Chunk Size" - }, - { - "type": "number", - "key": "deadline_priority", - "label": "Deadline Priotity" - }, - { - "type": "dict", - "key": "aov_filter", - "label": "Reviewable subsets filter", - "children": [ - { - "type": "list", - "key": "maya", - "label": "Maya", - "object_type": { - "type": "text" - } - }, - { - "type": "list", - "key": "nuke", - "label": "Nuke", - "object_type": { - "type": "text" - } - }, - { - "type": "list", - "key": "aftereffects", - "label": "After Effects", - "object_type": { - "type": "text" - } - }, - { - "type": "list", - "key": "celaction", - "label": "Celaction", - "object_type": { - "type": "text" - } - } - ] - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_global_tools.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_global_tools.json deleted file mode 100644 index d89477edd1..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_global_tools.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "tools", - "label": "Tools", - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "creator", - "label": "Creator", - "children": [ - { - "type": "dict-modifiable", - "collapsable": false, - "key": "families_smart_select", - "label": "Families smart select", - "object_type": { - "type": "list", - "object_type": "text" - } - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "Workfiles", - "label": "Workfiles", - "children": [ - { - "type": "list", - "key": "last_workfile_on_startup", - "label": "Open last workfiles on launch", - "is_group": true, - "use_label_wrap": true, - "object_type": { - "type": "dict", - "children": [ - { - "key": "hosts", - "label": "Hosts", - "type": "list", - "object_type": "text" - }, - { - "key": "tasks", - "label": "Tasks", - "type": "list", - "object_type": "text" - }, - { - "type": "splitter" - }, - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - } - ] - } - }, - { - "type": "dict-modifiable", - "collapsable": true, - "key": "sw_folders", - "label": "Extra task folders", - "is_group": true, - "object_type": { - "type": "list", - "object_type": "text" - } - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_capture.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_capture.json deleted file mode 100644 index ba7cf4b525..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_capture.json +++ /dev/null @@ -1,595 +0,0 @@ -{ - "type": "collapsible-wrap", - "label": "Collapsible Wrapper without key", - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "capture", - "label": "Maya Playblast settings", - "is_file": true, - "children": [ - { - "type": "dict", - "key": "Codec", - "children": [ - { - "type": "label", - "label": "Codec" - }, - { - "type": "text", - "key": "compression", - "label": "Compression type" - }, - { - "type": "text", - "key": "format", - "label": "Data format" - }, - { - "type": "number", - "key": "quality", - "label": "Quality", - "decimal": 0, - "minimum": 0, - "maximum": 100 - }, - - { - "type": "splitter" - } - ] - }, - { - "type": "dict", - "key": "Display Options", - "children": [ - { - "type": "label", - "label": "Display Options" - }, - { - "type": "list-strict", - "key": "background", - "label": "Background Color: ", - "object_types": [ - { - "label": "Red", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Green", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Blue", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - } - ] - }, - { - "type": "list-strict", - "key": "backgroundBottom", - "label": "Background Bottom: ", - "object_types": [ - { - "label": "Red", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Green", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Blue", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - } - ] - }, - { - "type": "list-strict", - "key": "backgroundTop", - "label": "Background Top: ", - "object_types": [ - { - "label": "Red", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Green", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Blue", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - } - ] - }, - { - "type": "boolean", - "key": "override_display", - "label": "Override display options" - } - ] - }, - { - "type": "splitter" - }, - { - "type": "dict", - "key": "Generic", - "children": [ - { - "type": "label", - "label": "Generic" - }, - { - "type": "boolean", - "key": "isolate_view", - "label": " Isolate view" - }, - { - "type": "boolean", - "key": "off_screen", - "label": " Off Screen" - } - ] - }, - { - "type": "dict", - "key": "IO", - "children": [ - { - "type": "label", - "label": "IO" - }, - { - "type": "text", - "key": "name", - "label": "Name" - }, - { - "type": "boolean", - "key": "open_finished", - "label": "Open finished" - }, - { - "type": "boolean", - "key": "raw_frame_numbers", - "label": "Raw frame numbers" - }, - { - "type": "list", - "key": "recent_playblasts", - "label": "Recent Playblasts", - "object_type": "text" - }, - { - "type": "boolean", - "key": "save_file", - "label": "Save file" - } - ] - }, - { - "type": "dict", - "key": "PanZoom", - "children": [ - { - "type": "boolean", - "key": "pan_zoom", - "label": " Pan Zoom" - } - ] - }, - { - "type": "splitter" - }, - { - "type": "dict", - "key": "Renderer", - "children": [ - { - "type": "label", - "label": "Renderer" - }, - { - "type": "text", - "key": "rendererName", - "label": " Renderer name" - } - ] - }, - { - "type": "dict", - "key": "Resolution", - "children": [ - { - "type": "splitter" - }, - { - "type": "label", - "label": "Resolution" - }, - { - "type": "number", - "key": "width", - "label": " Width", - "decimal": 0, - "minimum": 0, - "maximum": 99999 - }, - { - "type": "number", - "key": "height", - "label": "Height", - "decimal": 0, - "minimum": 0, - "maximum": 99999 - }, - { - "type": "number", - "key": "percent", - "label": "percent", - "decimal": 1, - "minimum": 0, - "maximum": 200 - }, - { - "type": "text", - "key": "mode", - "label": "Mode" - } - ] - }, - { - "type": "splitter" - }, - { - "type": "dict", - "key": "Time Range", - "children": [ - { - "type": "label", - "label": "Time Range" - }, - { - "type": "number", - "key": "start_frame", - "label": " Start frame", - "decimal": 0, - "minimum": 0, - "maximum": 999999 - }, - { - "type": "number", - "key": "end_frame", - "label": "End frame", - "decimal": 0, - "minimum": 0, - "maximum": 999999 - }, - { - "type": "text", - "key": "frame", - "label": "Frame" - }, - { - "type": "text", - "key": "time", - "label": "Time" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "Viewport Options", - "label": "Viewport Options", - "children": [ - { - "type": "boolean", - "key": "cameras", - "label": "cameras" - }, - { - "type": "boolean", - "key": "clipGhosts", - "label": "clipGhosts" - }, - { - "type": "boolean", - "key": "controlVertices", - "label": "controlVertices" - }, - { - "type": "boolean", - "key": "deformers", - "label": "deformers" - }, - { - "type": "boolean", - "key": "dimensions", - "label": "dimensions" - }, - { - "type": "number", - "key": "displayLights", - "label": "displayLights", - "decimal": 0, - "minimum": 0, - "maximum": 10 - }, - { - "type": "boolean", - "key": "dynamicConstraints", - "label": "dynamicConstraints" - }, - { - "type": "boolean", - "key": "dynamics", - "label": "dynamics" - }, - { - "type": "boolean", - "key": "fluids", - "label": "fluids" - }, - { - "type": "boolean", - "key": "follicles", - "label": "follicles" - }, - { - "type": "boolean", - "key": "gpuCacheDisplayFilter", - "label": "gpuCacheDisplayFilter" - }, - { - "type": "boolean", - "key": "greasePencils", - "label": "greasePencils" - }, - { - "type": "boolean", - "key": "grid", - "label": "grid" - }, - { - "type": "boolean", - "key": "hairSystems", - "label": "hairSystems" - }, - { - "type": "boolean", - "key": "handles", - "label": "handles" - }, - { - "type": "boolean", - "key": "high_quality", - "label": "high_quality" - }, - { - "type": "boolean", - "key": "hud", - "label": "hud" - }, - { - "type": "boolean", - "key": "hulls", - "label": "hulls" - }, - { - "type": "boolean", - "key": "ikHandles", - "label": "ikHandles" - }, - { - "type": "boolean", - "key": "imagePlane", - "label": "imagePlane" - }, - { - "type": "boolean", - "key": "joints", - "label": "joints" - }, - { - "type": "boolean", - "key": "lights", - "label": "lights" - }, - { - "type": "boolean", - "key": "locators", - "label": "locators" - }, - { - "type": "boolean", - "key": "manipulators", - "label": "manipulators" - }, - { - "type": "boolean", - "key": "motionTrails", - "label": "motionTrails" - }, - { - "type": "boolean", - "key": "nCloths", - "label": "nCloths" - }, - { - "type": "boolean", - "key": "nParticles", - "label": "nParticles" - }, - { - "type": "boolean", - "key": "nRigids", - "label": "nRigids" - }, - { - "type": "boolean", - "key": "nurbsCurves", - "label": "nurbsCurves" - }, - { - "type": "boolean", - "key": "nurbsSurfaces", - "label": "nurbsSurfaces" - }, - { - "type": "boolean", - "key": "override_viewport_options", - "label": "override_viewport_options" - }, - { - "type": "boolean", - "key": "particleInstancers", - "label": "particleInstancers" - }, - { - "type": "boolean", - "key": "pivots", - "label": "pivots" - }, - { - "type": "boolean", - "key": "planes", - "label": "planes" - }, - { - "type": "boolean", - "key": "pluginShapes", - "label": "pluginShapes" - }, - { - "type": "boolean", - "key": "polymeshes", - "label": "polymeshes" - }, - { - "type": "boolean", - "key": "shadows", - "label": "shadows" - }, - { - "type": "boolean", - "key": "strokes", - "label": "strokes" - }, - { - "type": "boolean", - "key": "subdivSurfaces", - "label": "subdivSurfaces" - }, - { - "type": "boolean", - "key": "textures", - "label": "textures" - }, - { - "type": "boolean", - "key": "twoSidedLighting", - "label": "twoSidedLighting" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "Camera Options", - "label": "Camera Options", - "children": [ - { - "type": "boolean", - "key": "displayGateMask", - "label": "displayGateMask" - }, - { - "type": "boolean", - "key": "displayResolution", - "label": "displayResolution" - }, - { - "type": "boolean", - "key": "displayFilmGate", - "label": "displayFilmGate" - }, - { - "type": "boolean", - "key": "displayFieldChart", - "label": "displayFieldChart" - }, - { - "type": "boolean", - "key": "displaySafeAction", - "label": "displaySafeAction" - }, - { - "type": "boolean", - "key": "displaySafeTitle", - "label": "displaySafeTitle" - }, - { - "type": "boolean", - "key": "displayFilmPivot", - "label": "displayFilmPivot" - }, - { - "type": "boolean", - "key": "displayFilmOrigin", - "label": "displayFilmOrigin" - }, - { - "type": "number", - "key": "overscan", - "label": "overscan", - "decimal": 1, - "minimum": 0, - "maximum": 10 - } - ] - } - ] - }, - { - "type": "dict-modifiable", - "key": "ext_mapping", - "label": "Extension Mapping", - "object_type": { - "type": "text" - } - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_load.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_load.json deleted file mode 100644 index 5aec3715bd..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_load.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "load", - "label": "Loader plugins", - "children": [ - { - "type": "dict", - "collapsable": true, - "key": "colors", - "label": "Loaded Subsets Outliner Colors", - "children": [ - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Model", - "name": "model" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Rig", - "name": "rig" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Pointcache", - "name": "pointcache" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Animation", - "name": "animation" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Arnold Standin", - "name": "ass" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Camera", - "name": "camera" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "FBX", - "name": "fbx" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Maya Scene", - "name": "mayaAscii" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Set Dress", - "name": "setdress" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Layout", - "name": "layout" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "VDB Cache", - "name": "vdbcache" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Vray Proxy", - "name": "vrayproxy" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Yeti Cache", - "name": "yeticache" - } - ] - }, - { - "type": "schema_template", - "name": "template_color", - "template_data": [ - { - "label": "Yeti Rig", - "name": "yetiRig" - } - ] - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_publish.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_publish.json deleted file mode 100644 index d1de128934..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_maya_publish.json +++ /dev/null @@ -1,214 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "publish", - "label": "Publish plugins", - "children": [ - { - "type": "label", - "label": "Collectors" - }, - { - "type": "dict", - "collapsable": true, - "key": "CollectMayaRender", - "label": "Collect Render Layers", - "children": [ - { - "type": "boolean", - "key": "sync_workfile_version", - "label": "Sync render version with workfile" - } - ] - }, - { - "type": "splitter" - }, - { - "type": "label", - "label": "Collectors" - }, - { - "type": "dict", - "collapsable": true, - "key": "ValidateCameraAttributes", - "label": "Validate Camera Attributes", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "ValidateModelName", - "label": "Validate Model Name", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Path to material file defining list of material names to check. This is material name per line simple text file.
It will be checked against named group shader in your Validation regex.

For example:
^.*(?P=<shader>.+)_GEO

" - }, - { - "type": "path-widget", - "key": "material_file", - "label": "Material File", - "multiplatform": true, - "multipath": false - }, - { - "type": "text", - "key": "regex", - "label": "Validation regex" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "ValidateAssemblyName", - "label": "Validate Assembly Name", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "ValidateShaderName", - "label": "ValidateShaderName", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "Shader name regex can use named capture group asset to validate against current asset name.

Example:
^.*(?P=<asset>.+)_SHD

" - }, - { - "type": "text", - "key": "regex", - "label": "Validation regex" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "ValidateMeshHasOverlappingUVs", - "label": "ValidateMeshHasOverlappingUVs", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "ValidateAttributes", - "label": "ValidateAttributes", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "raw-json", - "key": "attributes", - "label": "Attributes" - } - ] - }, - { - "type": "splitter" - }, - { - "type": "label", - "label": "Extractors" - }, - { - "type": "dict", - "collapsable": true, - "key": "ExtractCameraAlembic", - "label": "Extract camera to Alembic", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "label", - "label": "List of attributes that will be added to the baked alembic camera. Needs to be written in python list syntax.

For example:
[\"attributeName\", \"anotherAttribute\"]

" - }, - { - "type": "boolean", - "key": "optional", - "label": "Optional" - }, - { - "type": "raw-json", - "key": "bake_attributes", - "label": "Bake Attributes" - } - ] - }, - { - "type": "dict", - "collapsable": true, - "key": "MayaSubmitDeadline", - "label": "Submit maya job to deadline", - "checkbox_key": "enabled", - "children": [ - { - "type": "boolean", - "key": "enabled", - "label": "Enabled" - }, - { - "type": "enum", - "key": "tile_assembler_plugin", - "label": "Tile Assembler Plugin", - "multiselection": false, - "enum_items": [ - { - "DraftTileAssembler": "Draft Tile Assembler" - }, - { - "oiio": "Open Image IO" - } - ] - } - ] - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_publish_gui_filter.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_publish_gui_filter.json deleted file mode 100644 index efc6c1d629..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_publish_gui_filter.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "type": "dict-modifiable", - "collapsable": true, - "key": "filters", - "label": "Publish GUI Filters", - "object_type": { - "type": "raw-json", - "label": "Plugins" - } -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_workfile_build.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_workfile_build.json deleted file mode 100644 index bf0aff2d41..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/schema_workfile_build.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "type": "dict", - "collapsable": true, - "key": "workfile_build", - "label": "Workfile Build Settings", - "children": [ - { - "type": "list", - "key": "profiles", - "label": "Profiles", - "object_type": { - "type": "dict", - "children": [ - { - "key": "tasks", - "label": "Tasks", - "type": "list", - "object_type": "text" - }, - { - "type": "splitter" - }, - { - "key": "current_context", - "label": "Current Context", - "type": "list", - "highlight_content": true, - "object_type": { - "type": "dict", - "children": [ - { - "key": "subset_name_filters", - "label": "Subset name Filters", - "type": "list", - "object_type": "text" - }, - { - "key": "families", - "label": "Families", - "type": "list", - "object_type": "text" - }, - { - "key": "repre_names", - "label": "Repre Names", - "type": "list", - "object_type": "text" - }, - { - "key": "loaders", - "label": "Loaders", - "type": "list", - "object_type": "text" - } - ] - } - }, - { - "key": "linked_assets", - "label": "Linked Assets", - "type": "list", - "highlight_content": true, - "object_type": { - "type": "dict", - "children": [ - { - "key": "subset_name_filters", - "label": "Subset name Filters", - "type": "list", - "object_type": "text" - }, - { - "key": "families", - "label": "Families", - "type": "list", - "object_type": "text" - }, - { - "key": "repre_names", - "label": "Repre Names", - "type": "list", - "object_type": "text" - }, - { - "key": "loaders", - "label": "Loaders", - "type": "list", - "object_type": "text" - } - ] - } - } - ] - } - } - ] -} diff --git a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/template_color.json b/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/template_color.json deleted file mode 100644 index 04ce055525..0000000000 --- a/pype/tools/settings/settings/gui_schemas/projects_schema/schemas/template_color.json +++ /dev/null @@ -1,30 +0,0 @@ -[ - { - "type": "list-strict", - "key": "{name}", - "label": "{label}:", - "object_types": [ - { - "label": "Red", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Green", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - }, - { - "label": "Blue", - "type": "number", - "minimum": 0, - "maximum": 1, - "decimal": 3 - } - ] - } -] From e0993464e00e049bf16b89f54cd07b66cd835ec3 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 10:13:51 +0100 Subject: [PATCH 55/83] removed temporarily project structure wrapper --- .../schema_project_global.json | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_global.json b/pype/settings/entities/schemas/projects_schema/schema_project_global.json index ab9b56115d..09aa424e57 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_global.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_global.json @@ -13,21 +13,14 @@ "type": "schema", "name": "schema_global_tools" }, - - { - "type": "collapsible-wrap", - "label": "Project Folder Structure", - "children": [ - { - "type": "raw-json", - "key": "project_folder_structure" - } - ] - }, - - { - "type": "schema", - "name": "schema_project_syncserver" - } + { + "type": "raw-json", + "label": "Project Folder Structure", + "key": "project_folder_structure" + }, + { + "type": "schema", + "name": "schema_project_syncserver" + } ] } From 7d3445470c993ac61b4dae10b05b2636f8550181 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 12:22:07 +0100 Subject: [PATCH 56/83] fix remove project action --- pype/settings/entities/root_entities.py | 7 ++++--- pype/tools/settings/settings/widgets/base.py | 7 +++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index dd895d9899..8070b65698 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -184,10 +184,11 @@ class RootEntity(BaseItemEntity): if not issubclass(item, entities.BaseEntity): continue + # Skip class that is abstract by design + if item in known_abstract_classes: + continue + if inspect.isabstract(item): - # Skip class that is abstract by design - if item in known_abstract_classes: - continue # Create an object to get crash and get traceback item() diff --git a/pype/tools/settings/settings/widgets/base.py b/pype/tools/settings/settings/widgets/base.py index acebba0e3a..673e34639f 100644 --- a/pype/tools/settings/settings/widgets/base.py +++ b/pype/tools/settings/settings/widgets/base.py @@ -143,9 +143,12 @@ class BaseWidget(QtWidgets.QWidget): elif not self.entity.has_project_override: return - # TODO better label + def remove_from_project_override(): + self.ignore_input_changes.set_ignore(True) + self.entity.remove_from_project_override() + self.ignore_input_changes.set_ignore(False) action = QtWidgets.QAction("Remove from project override") - actions_mapping[action] = self.entity.remove_from_project_override + actions_mapping[action] = remove_from_project_override menu.addAction(action) def show_actions_menu(self, event=None): From 28e3c25f113adba0a669c2cd2f1478150ac4f950 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 12:23:19 +0100 Subject: [PATCH 57/83] category widget is accessible from all widgets --- pype/tools/settings/settings/widgets/base.py | 3 +- .../settings/settings/widgets/categories.py | 29 ++++++++++--------- .../settings/widgets/dict_mutable_widget.py | 12 ++++++-- .../settings/settings/widgets/item_widgets.py | 6 ++-- .../settings/widgets/list_item_widget.py | 8 ++++- .../settings/widgets/list_strict_widget.py | 4 ++- 6 files changed, 41 insertions(+), 21 deletions(-) diff --git a/pype/tools/settings/settings/widgets/base.py b/pype/tools/settings/settings/widgets/base.py index 673e34639f..6bd71a931e 100644 --- a/pype/tools/settings/settings/widgets/base.py +++ b/pype/tools/settings/settings/widgets/base.py @@ -4,7 +4,8 @@ from Qt import QtWidgets, QtGui, QtCore class BaseWidget(QtWidgets.QWidget): allow_actions = True - def __init__(self, entity, entity_widget): + def __init__(self, category_widget, entity, entity_widget): + self.category_widget = category_widget self.entity = entity self.entity_widget = entity_widget diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index c1964faebf..48041bd607 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -93,42 +93,43 @@ class SettingsCategoryWidget(QtWidgets.QWidget): self.create_ui() @staticmethod - def create_ui_for_entity(entity, entity_widget): + def create_ui_for_entity(category_widget, entity, entity_widget): + args = (category_widget, entity, entity_widget) if isinstance(entity, GUIEntity): - return GUIWidget(entity, entity_widget) + return GUIWidget(*args) elif isinstance(entity, DictImmutableKeysEntity): - return DictImmutableKeysWidget(entity, entity_widget) + return DictImmutableKeysWidget(*args) elif isinstance(entity, BoolEntity): - return BoolWidget(entity, entity_widget) + return BoolWidget(*args) elif isinstance(entity, TextEntity): - return TextWidget(entity, entity_widget) + return TextWidget(*args) elif isinstance(entity, NumberEntity): - return NumberWidget(entity, entity_widget) + return NumberWidget(*args) elif isinstance(entity, RawJsonEntity): - return RawJsonWidget(entity, entity_widget) + return RawJsonWidget(*args) elif isinstance(entity, EnumEntity): - return EnumeratorWidget(entity, entity_widget) + return EnumeratorWidget(*args) elif isinstance(entity, PathEntity): - return PathWidget(entity, entity_widget) + return PathWidget(*args) elif isinstance(entity, PathInput): - return PathInputWidget(entity, entity_widget) + return PathInputWidget(*args) elif isinstance(entity, ListEntity): - return ListWidget(entity, entity_widget) + return ListWidget(*args) elif isinstance(entity, DictMutableKeysEntity): - return DictMutableKeysWidget(entity, entity_widget) + return DictMutableKeysWidget(*args) elif isinstance(entity, ListStrictEntity): - return ListStrictWidget(entity, entity_widget) + return ListStrictWidget(*args) label = "<{}>: {} ({})".format( entity.__class__.__name__, entity.path, entity.value @@ -298,7 +299,7 @@ class SettingsCategoryWidget(QtWidgets.QWidget): def add_children_gui(self): for child_obj in self.entity.children: - item = self.create_ui_for_entity(child_obj, self) + item = self.create_ui_for_entity(self, child_obj, self) self.input_fields.append(item) # Add spacer to stretch children guis diff --git a/pype/tools/settings/settings/widgets/dict_mutable_widget.py b/pype/tools/settings/settings/widgets/dict_mutable_widget.py index 63f0ee539a..5d3f669654 100644 --- a/pype/tools/settings/settings/widgets/dict_mutable_widget.py +++ b/pype/tools/settings/settings/widgets/dict_mutable_widget.py @@ -178,6 +178,10 @@ class ModifiableDictItem(QtWidgets.QWidget): self.create_addible_ui() self.update_style() + @property + def category_widget(self): + return self.entity_widget.category_widget + def create_addible_ui(self): key_input = QtWidgets.QLineEdit(self) key_input.setObjectName("DictKey") @@ -205,7 +209,9 @@ class ModifiableDictItem(QtWidgets.QWidget): self.content_widget = self self.content_layout = layout - self.input_field = self.create_ui_for_entity(self.entity, self) + self.input_field = self.create_ui_for_entity( + self.category_widget, self.entity, self + ) def add_widget_to_layout(self, widget, label=None): self.content_layout.addWidget(widget, 1) @@ -288,7 +294,9 @@ class ModifiableDictItem(QtWidgets.QWidget): self.content_widget = content_widget self.content_layout = content_layout - self.input_field = self.create_ui_for_entity(self.entity, self) + self.input_field = self.create_ui_for_entity( + self.category_widget, self.entity, self + ) def get_style_state(self): if self.is_invalid: diff --git a/pype/tools/settings/settings/widgets/item_widgets.py b/pype/tools/settings/settings/widgets/item_widgets.py index 162dac266d..fd33f337d7 100644 --- a/pype/tools/settings/settings/widgets/item_widgets.py +++ b/pype/tools/settings/settings/widgets/item_widgets.py @@ -45,7 +45,9 @@ class DictImmutableKeysWidget(BaseWidget): for child_obj in self.entity.children: self.input_fields.append( - self.create_ui_for_entity(child_obj, self) + self.create_ui_for_entity( + self.category_widget, child_obj, self + ) ) self.entity_widget.add_widget_to_layout(self) @@ -508,7 +510,7 @@ class PathWidget(BaseWidget): self.content_layout.setSpacing(5) self.input_field = self.create_ui_for_entity( - self.entity.child_obj, self + self.category_widget, self.entity.child_obj, self ) self.entity_widget.add_widget_to_layout(self, self.entity.label) diff --git a/pype/tools/settings/settings/widgets/list_item_widget.py b/pype/tools/settings/settings/widgets/list_item_widget.py index 07de7da112..c45525f8bc 100644 --- a/pype/tools/settings/settings/widgets/list_item_widget.py +++ b/pype/tools/settings/settings/widgets/list_item_widget.py @@ -98,7 +98,9 @@ class ListItem(QtWidgets.QWidget): self.content_widget = self self.content_layout = layout - self.input_field = self.create_ui_for_entity(self.entity, self) + self.input_field = self.create_ui_for_entity( + self.category_widget, self.entity, self + ) self.input_field.set_entity_value() spacer_widget = QtWidgets.QWidget(self) @@ -117,6 +119,10 @@ class ListItem(QtWidgets.QWidget): self.spacer_widget = spacer_widget + @property + def category_widget(self): + return self.entity_widget.category_widget + @property def is_invalid(self): return self.input_field.is_invalid diff --git a/pype/tools/settings/settings/widgets/list_strict_widget.py b/pype/tools/settings/settings/widgets/list_strict_widget.py index 1167bf4cdb..340db2e8c6 100644 --- a/pype/tools/settings/settings/widgets/list_strict_widget.py +++ b/pype/tools/settings/settings/widgets/list_strict_widget.py @@ -35,7 +35,9 @@ class ListStrictWidget(BaseWidget): for child_obj in self.entity.children: self.input_fields.append( - self.create_ui_for_entity(child_obj, self) + self.create_ui_for_entity( + self.category_widget, child_obj, self + ) ) if self.entity.is_horizontal: From 527faa8c41c08d9dc5e9c3b14c2b1c7e6c790589 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 12:23:36 +0100 Subject: [PATCH 58/83] create_ui_for_entity is always defined as method --- pype/tools/settings/settings/widgets/base.py | 4 +++- pype/tools/settings/settings/widgets/dict_mutable_widget.py | 4 +++- pype/tools/settings/settings/widgets/list_item_widget.py | 6 +++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pype/tools/settings/settings/widgets/base.py b/pype/tools/settings/settings/widgets/base.py index 6bd71a931e..0dbf17d42f 100644 --- a/pype/tools/settings/settings/widgets/base.py +++ b/pype/tools/settings/settings/widgets/base.py @@ -13,7 +13,6 @@ class BaseWidget(QtWidgets.QWidget): self.entity_widget.trigger_hierarchical_style_update ) self.ignore_input_changes = entity_widget.ignore_input_changes - self.create_ui_for_entity = entity_widget.create_ui_for_entity self._is_invalid = False self._style_state = None @@ -25,6 +24,9 @@ class BaseWidget(QtWidgets.QWidget): self.label_widget = None self.create_ui() + def create_ui_for_entity(self, *args, **kwargs): + return self.category_widget.create_ui_for_entity(*args, **kwargs) + @property def is_invalid(self): return self._is_invalid diff --git a/pype/tools/settings/settings/widgets/dict_mutable_widget.py b/pype/tools/settings/settings/widgets/dict_mutable_widget.py index 5d3f669654..337aa661cf 100644 --- a/pype/tools/settings/settings/widgets/dict_mutable_widget.py +++ b/pype/tools/settings/settings/widgets/dict_mutable_widget.py @@ -156,7 +156,6 @@ class ModifiableDictItem(QtWidgets.QWidget): self.entity = entity self.entity_widget = entity_widget - self.create_ui_for_entity = entity_widget.create_ui_for_entity self.ignore_input_changes = entity_widget.ignore_input_changes self.is_key_duplicated = False @@ -182,6 +181,9 @@ class ModifiableDictItem(QtWidgets.QWidget): def category_widget(self): return self.entity_widget.category_widget + def create_ui_for_entity(self, *args, **kwargs): + return self.entity_widget.create_ui_for_entity(*args, **kwargs) + def create_addible_ui(self): key_input = QtWidgets.QLineEdit(self) key_input.setObjectName("DictKey") diff --git a/pype/tools/settings/settings/widgets/list_item_widget.py b/pype/tools/settings/settings/widgets/list_item_widget.py index c45525f8bc..a7f3438987 100644 --- a/pype/tools/settings/settings/widgets/list_item_widget.py +++ b/pype/tools/settings/settings/widgets/list_item_widget.py @@ -54,7 +54,6 @@ class ListItem(QtWidgets.QWidget): self.entity = entity self.ignore_input_changes = entity_widget.ignore_input_changes - self.create_ui_for_entity = entity_widget.create_ui_for_entity char_up = qtawesome.charmap("fa.angle-up") char_down = qtawesome.charmap("fa.angle-down") @@ -123,6 +122,11 @@ class ListItem(QtWidgets.QWidget): def category_widget(self): return self.entity_widget.category_widget + def create_ui_for_entity(self, *args, **kwargs): + return self.entity_widget.create_ui_for_entity( + *args, **kwargs + ) + @property def is_invalid(self): return self.input_field.is_invalid From 37cb2b1db273f5ea866af74753c042f7ab0255b0 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 12:47:46 +0100 Subject: [PATCH 59/83] fix metadata modification check --- .../entities/dict_immutable_keys_entity.py | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/pype/settings/entities/dict_immutable_keys_entity.py b/pype/settings/entities/dict_immutable_keys_entity.py index 642fde9685..2223bfe65f 100644 --- a/pype/settings/entities/dict_immutable_keys_entity.py +++ b/pype/settings/entities/dict_immutable_keys_entity.py @@ -192,22 +192,6 @@ class DictImmutableKeysEntity(ItemEntity): return "/".join([self.path, result_key]) def _update_current_metadata(self): - # Define if current metadata are avaialble for current override state - metadata = NOT_SET - if self._override_state is OverrideState.DEFAULTS: - metadata = {} - - if self._override_state is OverrideState.PROJECT: - # metadata are NOT_SET if project overrides do not override this - # item - metadata = self._project_override_metadata - - if ( - self._override_state >= OverrideState.STUDIO - and metadata is NOT_SET - ): - metadata = self._studio_override_metadata - current_metadata = {} for key, child_obj in self.non_gui_children.items(): if self._override_state is OverrideState.DEFAULTS: @@ -232,10 +216,18 @@ class DictImmutableKeysEntity(ItemEntity): current_metadata[M_OVERRIDEN_KEY] = [] current_metadata[M_OVERRIDEN_KEY].append(key) - if metadata is NOT_SET and not current_metadata: - self._metadata_are_modified = False - else: - self._metadata_are_modified = current_metadata != metadata + # Define if current metadata are avaialble for current override state + metadata = NOT_SET + if self._override_state is OverrideState.STUDIO: + metadata = self._studio_override_metadata + + elif self._override_state is OverrideState.PROJECT: + metadata = self._project_override_metadata + + if metadata is NOT_SET: + metadata = {} + + self._metadata_are_modified = current_metadata != metadata self._current_metadata = current_metadata def set_override_state(self, state): From 2d1e98ec983aec1b1cd6d340dd2151125becb7b5 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 13:36:02 +0100 Subject: [PATCH 60/83] fix remove project overrides --- pype/settings/entities/list_entity.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pype/settings/entities/list_entity.py b/pype/settings/entities/list_entity.py index 9002fe9bf7..943863c3e0 100644 --- a/pype/settings/entities/list_entity.py +++ b/pype/settings/entities/list_entity.py @@ -407,6 +407,9 @@ class ListEntity(EndpointEntity): self._ignore_child_changes = True + while self.children: + self.children.pop(0) + for item in value: child_obj = self._add_new_item() child_obj.update_default_value(item) From f62fade14be4609a27c1b6ef2fb2e581095a5e5d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 13:37:26 +0100 Subject: [PATCH 61/83] fix remove overrides action discovery --- pype/tools/settings/settings/widgets/base.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/pype/tools/settings/settings/widgets/base.py b/pype/tools/settings/settings/widgets/base.py index 0dbf17d42f..381a075122 100644 --- a/pype/tools/settings/settings/widgets/base.py +++ b/pype/tools/settings/settings/widgets/base.py @@ -135,15 +135,10 @@ class BaseWidget(QtWidgets.QWidget): if self.entity.is_dynamic_item or self.entity.is_in_dynamic_item: return - if self.entity.is_group: - if not self.entity.has_project_override: - return + if not self.entity.has_project_override: + return - elif self.entity.group_item: - if not self.entity.group_item.has_project_override: - return - - elif not self.entity.has_project_override: + if not self.entity.root_item.is_in_project_state(): return def remove_from_project_override(): From a1503da01ad0f36d416155bf9a1e031367a348ba Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 14:39:19 +0100 Subject: [PATCH 62/83] fixed mutable dict overrides removement --- pype/settings/entities/dict_mutable_keys_entity.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index 9a016b3afc..c3209e2538 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -459,7 +459,7 @@ class DictMutableKeysEntity(EndpointEntity): # Create new children for _key, _value in new_value.items(): - child_obj = self.add_key(_key) + child_obj = self._add_key(_key) child_obj.update_default_value(_value) child_obj.set_override_state(self._override_state) @@ -482,10 +482,8 @@ class DictMutableKeysEntity(EndpointEntity): if not self.has_project_override: return - using_overrides = False if self._has_studio_override: value = self._studio_override_value - using_overrides = True elif self.has_default_value: value = self._default_value else: @@ -501,9 +499,9 @@ class DictMutableKeysEntity(EndpointEntity): # Create new children for _key, _value in new_value.items(): - child_obj = self.add_key(_key) + child_obj = self._add_key(_key) child_obj.update_default_value(_value) - if using_overrides: + if self._has_studio_override: child_obj.update_studio_value(_value) child_obj.set_override_state(self._override_state) From e1b56801b5f3b9f4f1af8df4009ccc89e00aeca8 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 15:02:48 +0100 Subject: [PATCH 63/83] tell which overrides are used --- .../entities/dict_mutable_keys_entity.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index c3209e2538..1e130f0a29 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -258,20 +258,25 @@ class DictMutableKeysEntity(EndpointEntity): self._has_project_override = self.had_project_override self._has_studio_override = self.had_studio_override - using_overrides = True + using_project_overrides = False + using_studio_overrides = False if ( state is OverrideState.PROJECT and self.had_project_override ): + using_project_overrides = True value = self._project_override_value metadata = self._project_override_metadata - elif self.had_studio_override: + elif ( + state >= OverrideState.STUDIO + and self.had_studio_override + ): + using_studio_overrides = True value = self._studio_override_value metadata = self._studio_override_metadata else: - using_overrides = False value = self._default_value metadata = self._default_metadata @@ -290,11 +295,10 @@ class DictMutableKeysEntity(EndpointEntity): for _key, _value in new_value.items(): child_obj = self._add_key(_key) child_obj.update_default_value(_value) - if using_overrides: - if state is OverrideState.STUDIO: - child_obj.update_studio_value(_value) - else: - child_obj.update_project_value(_value) + if using_project_overrides: + child_obj.update_project_value(_value) + elif using_studio_overrides: + child_obj.update_studio_value(_value) label = metadata_labels.get(_key) if label: From c0a1144490e3d7b6ab7954789fddba071177cb9b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 15:29:22 +0100 Subject: [PATCH 64/83] actions availability is defined in entities --- pype/settings/entities/base_entity.py | 115 +++++++++++++++++-- pype/tools/settings/settings/widgets/base.py | 70 ++++------- 2 files changed, 126 insertions(+), 59 deletions(-) diff --git a/pype/settings/entities/base_entity.py b/pype/settings/entities/base_entity.py index 49fd24aae8..295d83507b 100644 --- a/pype/settings/entities/base_entity.py +++ b/pype/settings/entities/base_entity.py @@ -417,6 +417,94 @@ class BaseItemEntity(BaseEntity): """Value of entity without metadata.""" pass + @property + def can_discard_changes(self): + """Result defines if `discard_changes` will be processed. + + Also can be used as validation before the method is called. + """ + return self.has_unsaved_changes + + @property + def can_add_to_studio_default(self): + """Result defines if `add_to_studio_default` will be processed. + + Also can be used as validation before the method is called. + """ + if self._override_state is not OverrideState.STUDIO: + return False + + if self.is_dynamic_item or self.is_in_dynamic_item: + return False + + # Skip if entity is under group + if self.group_item: + return False + + # Skip if is group and any children is already marked with studio + # overrides + if self.is_group and self.has_studio_override: + return False + return True + + @property + def can_remove_from_studio_default(self): + """Result defines if `remove_from_studio_default` can be triggered. + + This can be also used as validation before the method is called. + """ + if self._override_state is not OverrideState.STUDIO: + return False + + if self.is_dynamic_item or self.is_in_dynamic_item: + return False + + if not self.has_studio_override: + return False + return True + + @property + def can_add_to_project_override(self): + """Result defines if `add_to_project_override` can be triggered. + + Also can be used as validation before the method is called. + """ + if self.is_dynamic_item or self.is_in_dynamic_item: + return False + + # Show only when project overrides are set + if self._override_state is not OverrideState.PROJECT: + return False + + # Do not show on items under group item + if self.group_item: + return False + + # Skip if already is marked to save project overrides + if self.is_group and self.has_studio_override: + return False + return True + + @property + def can_remove_from_project_override(self): + """Result defines if `remove_from_project_override` can be triggered. + + This can be also used as validation before the method is called. + """ + if self.is_dynamic_item or self.is_in_dynamic_item: + return False + + if self._override_state is not OverrideState.PROJECT: + return False + + # Dynamic items can't have these actions + if self.is_dynamic_item or self.is_in_dynamic_item: + return False + + if not self.has_project_override: + return False + return True + def discard_changes(self, on_change_trigger=None): """Discard changes on entity and it's children. @@ -441,6 +529,9 @@ class BaseItemEntity(BaseEntity): """ initialized = False if on_change_trigger is None: + if not self.can_discard_changes: + return + initialized = True on_change_trigger = [] @@ -478,11 +569,11 @@ class BaseItemEntity(BaseEntity): on_change_trigger (list): Callbacks of `on_change` should be stored to trigger them afterwards. """ - if self._override_state is not OverrideState.STUDIO: - return - initialized = False if on_change_trigger is None: + if not self.can_remove_from_studio_default: + return + initialized = True on_change_trigger = [] @@ -501,6 +592,14 @@ class BaseItemEntity(BaseEntity): """ pass + @abstractmethod + def add_to_project_override(self): + """Item's implementation to set values as overriden for project. + + Mark item and all it's children to be stored as project overrides. + """ + pass + def remove_from_project_override(self, on_change_trigger=None): """Remove project overrides from entity and it's children. @@ -521,6 +620,8 @@ class BaseItemEntity(BaseEntity): initialized = False if on_change_trigger is None: + if not self.can_remove_from_project_override: + return initialized = True on_change_trigger = [] @@ -530,14 +631,6 @@ class BaseItemEntity(BaseEntity): for callback in on_change_trigger: callback() - @abstractmethod - def add_to_project_override(self): - """Item's implementation to set values as overriden for project. - - Mark item and all it's children to be stored as project overrides. - """ - pass - @abstractmethod def _remove_from_project_override(self, on_change_trigger): """Item's implementation to remove project overrides. diff --git a/pype/tools/settings/settings/widgets/base.py b/pype/tools/settings/settings/widgets/base.py index 381a075122..3a80bb936b 100644 --- a/pype/tools/settings/settings/widgets/base.py +++ b/pype/tools/settings/settings/widgets/base.py @@ -69,7 +69,7 @@ class BaseWidget(QtWidgets.QWidget): def _discard_changes_action(self, menu, actions_mapping): # TODO use better condition as unsaved changes may be caused due to # changes in schema. - if not self.entity.has_unsaved_changes: + if not self.entity.can_discard_changes: return def discard_changes(): @@ -81,64 +81,38 @@ class BaseWidget(QtWidgets.QWidget): actions_mapping[action] = discard_changes menu.addAction(action) - def _set_project_override_action(self, menu, actions_mapping): - # Show only when project overrides are set - if not self.entity.root_item.is_in_project_state(): - return - - # Do not show on items under group item - if self.entity.group_item: - return - - # Skip if already is marked to save project overrides - if self.entity.is_group and self.entity.has_studio_override: - return - - action = QtWidgets.QAction("Add to project project override") - actions_mapping[action] = self.entity.add_to_project_override - menu.addAction(action) - - def _remove_from_studio_default_action(self, menu, actions_mapping): - if not self.entity.root_item.is_in_studio_state(): - return - - if self.entity.has_studio_override: - def remove_from_studio_default(): - self.ignore_input_changes.set_ignore(True) - self.entity.remove_from_studio_default() - self.ignore_input_changes.set_ignore(False) - action = QtWidgets.QAction("Remove from studio default") - actions_mapping[action] = remove_from_studio_default - menu.addAction(action) - def _add_to_studio_default(self, menu, actions_mapping): """Set values as studio overrides.""" # Skip if not in studio overrides - if not self.entity.root_item.is_in_studio_state(): - return - - # Skip if entity is under group - if self.entity.group_item: - return - - # Skip if is group and any children is already marked with studio - # overrides - if self.entity.is_group and self.entity.has_studio_override: + if not self.entity.can_add_to_studio_default: return action = QtWidgets.QAction("Add to studio default") actions_mapping[action] = self.entity.add_to_studio_default menu.addAction(action) - def _remove_project_override_action(self, menu, actions_mapping): - # Dynamic items can't have these actions - if self.entity.is_dynamic_item or self.entity.is_in_dynamic_item: + def _remove_from_studio_default_action(self, menu, actions_mapping): + if not self.entity.can_remove_from_studio_default: return - if not self.entity.has_project_override: + def remove_from_studio_default(): + self.ignore_input_changes.set_ignore(True) + self.entity.remove_from_studio_default() + self.ignore_input_changes.set_ignore(False) + action = QtWidgets.QAction("Remove from studio default") + actions_mapping[action] = remove_from_studio_default + menu.addAction(action) + + def _add_to_project_override_action(self, menu, actions_mapping): + if not self.entity.can_add_to_project_override: return - if not self.entity.root_item.is_in_project_state(): + action = QtWidgets.QAction("Add to project project override") + actions_mapping[action] = self.entity.add_to_project_override + menu.addAction(action) + + def _remove_from_project_override_action(self, menu, actions_mapping): + if not self.entity.can_remove_from_project_override: return def remove_from_project_override(): @@ -165,8 +139,8 @@ class BaseWidget(QtWidgets.QWidget): self._discard_changes_action(menu, actions_mapping) self._add_to_studio_default(menu, actions_mapping) self._remove_from_studio_default_action(menu, actions_mapping) - self._set_project_override_action(menu, actions_mapping) - self._remove_project_override_action(menu, actions_mapping) + self._add_to_project_override_action(menu, actions_mapping) + self._remove_from_project_override_action(menu, actions_mapping) if not actions_mapping: action = QtWidgets.QAction("< No action >") From cfb339da73b6b805f4b9ec248408a1700c7992fc Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 15:48:05 +0100 Subject: [PATCH 65/83] all actions have wrappers --- pype/settings/entities/base_entity.py | 34 +++++++++++++++++-- .../entities/dict_immutable_keys_entity.py | 14 +++----- .../entities/dict_mutable_keys_entity.py | 8 ++--- pype/settings/entities/input_entities.py | 8 ++--- pype/settings/entities/item_entities.py | 29 +++++++--------- pype/settings/entities/list_entity.py | 6 ++-- pype/settings/entities/root_entities.py | 8 ++--- 7 files changed, 58 insertions(+), 49 deletions(-) diff --git a/pype/settings/entities/base_entity.py b/pype/settings/entities/base_entity.py index 295d83507b..187e1abb60 100644 --- a/pype/settings/entities/base_entity.py +++ b/pype/settings/entities/base_entity.py @@ -546,8 +546,23 @@ class BaseItemEntity(BaseEntity): """Entity's implementation to discard all changes made by user.""" pass + def add_to_studio_default(self, on_change_trigger=None): + initialized = False + if on_change_trigger is None: + if not self.can_add_to_studio_default: + return + + initialized = True + on_change_trigger = [] + + self._add_to_studio_default(on_change_trigger) + + if initialized: + for callback in on_change_trigger: + callback() + @abstractmethod - def add_to_studio_default(self): + def _add_to_studio_default(self, on_change_trigger): """Item's implementation to set current values as studio's overrides. Mark item and it's children as they have studio overrides. @@ -592,8 +607,23 @@ class BaseItemEntity(BaseEntity): """ pass + def add_to_project_override(self, on_change_trigger=None): + initialized = False + if on_change_trigger is None: + if not self.can_add_to_project_override: + return + + initialized = True + on_change_trigger = [] + + self._add_to_project_override(on_change_trigger) + + if initialized: + for callback in on_change_trigger: + callback() + @abstractmethod - def add_to_project_override(self): + def _add_to_project_override(self, on_change_trigger): """Item's implementation to set values as overriden for project. Mark item and all it's children to be stored as project overrides. diff --git a/pype/settings/entities/dict_immutable_keys_entity.py b/pype/settings/entities/dict_immutable_keys_entity.py index 2223bfe65f..c983dace2c 100644 --- a/pype/settings/entities/dict_immutable_keys_entity.py +++ b/pype/settings/entities/dict_immutable_keys_entity.py @@ -435,13 +435,10 @@ class DictImmutableKeysEntity(ItemEntity): self._ignore_child_changes = False - def add_to_studio_default(self): - if self._override_state is not OverrideState.STUDIO: - return - + def _add_to_studio_default(self, on_change_trigger): self._ignore_child_changes = True for child_obj in self.non_gui_children.values(): - child_obj.add_to_studio_default() + child_obj.add_to_studio_default(on_change_trigger) self._ignore_child_changes = False self.parent.on_child_change(self) @@ -451,13 +448,10 @@ class DictImmutableKeysEntity(ItemEntity): child_obj.remove_from_studio_default(on_change_trigger) self._ignore_child_changes = False - def add_to_project_override(self): - if self._override_state is not OverrideState.PROJECT: - return - + def _add_to_project_override(self, _on_change_trigger): self._ignore_child_changes = True for child_obj in self.non_gui_children.values(): - child_obj.add_to_project_override() + child_obj.add_to_project_override(_on_change_trigger) self._ignore_child_changes = False self.parent.on_child_change(self) diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index 1e130f0a29..f8c86a3159 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -443,9 +443,7 @@ class DictMutableKeysEntity(EndpointEntity): self.set_override_state(self._override_state) on_change_trigger.append(self.on_change) - def add_to_studio_default(self): - if self._override_state is not OverrideState.STUDIO: - return + def _add_to_studio_default(self, _on_change_trigger): self._has_studio_override = True self.on_change() @@ -473,9 +471,7 @@ class DictMutableKeysEntity(EndpointEntity): on_change_trigger.append(self.on_change) - def add_to_project_override(self): - if self._override_state is not OverrideState.PROJECT: - return + def _add_to_project_override(self, _on_change_trigger): self._has_project_override = True self.on_change() diff --git a/pype/settings/entities/input_entities.py b/pype/settings/entities/input_entities.py index f113cca0f5..0f9f5c8a36 100644 --- a/pype/settings/entities/input_entities.py +++ b/pype/settings/entities/input_entities.py @@ -276,9 +276,7 @@ class InputEntity(EndpointEntity): raise NotImplementedError("BUG: Unexcpected part of code.") - def add_to_studio_default(self): - if self._override_state is not OverrideState.STUDIO: - return + def _add_to_studio_default(self, _on_change_trigger): self._has_studio_override = True self.on_change() @@ -293,9 +291,7 @@ class InputEntity(EndpointEntity): on_change_trigger.append(self.on_change) - def add_to_project_override(self): - if self._override_state is not OverrideState.PROJECT: - return + def _add_to_project_override(self, _on_change_trigger): self._has_project_override = True self.on_change() diff --git a/pype/settings/entities/item_entities.py b/pype/settings/entities/item_entities.py index 20a7dbc513..30be845d60 100644 --- a/pype/settings/entities/item_entities.py +++ b/pype/settings/entities/item_entities.py @@ -162,20 +162,20 @@ class PathEntity(ItemEntity): def update_studio_value(self, value): self.child_obj.update_studio_value(value) - def _discard_changes(self, *args): - self.child_obj.discard_changes(*args) + def _discard_changes(self, *args, **kwargs): + self.child_obj.discard_changes(*args, **kwargs) - def add_to_studio_default(self): - self.child_obj.add_to_studio_default() + def _add_to_studio_default(self, *args, **kwargs): + self.child_obj.add_to_studio_default(*args, **kwargs) - def _remove_from_studio_default(self, *args): - self.child_obj.remove_from_studio_default(*args) + def _remove_from_studio_default(self, *args, **kwargs): + self.child_obj.remove_from_studio_default(*args, **kwargs) - def add_to_project_override(self): - self.child_obj.add_to_project_override() + def _add_to_project_override(self, *args, **kwargs): + self.child_obj.add_to_project_override(*args, **kwargs) - def _remove_from_project_override(self, *args): - self.child_obj.remove_from_project_override(*args) + def _remove_from_project_override(self, *args, **kwargs): + self.child_obj.remove_from_project_override(*args, **kwargs) def reset_callbacks(self): super(PathEntity, self).reset_callbacks() @@ -359,9 +359,7 @@ class ListStrictEntity(ItemEntity): for child_obj in self.children: child_obj.discard_changes(on_change_trigger) - def add_to_studio_default(self): - if self._override_state is not OverrideState.STUDIO: - return + def _add_to_studio_default(self, _on_change_trigger): self._has_studio_override = True self.on_change() @@ -375,14 +373,11 @@ class ListStrictEntity(ItemEntity): self._has_studio_override = False - def add_to_project_override(self): + def _add_to_project_override(self, _on_change_trigger): self._has_project_override = True self.on_change() def _remove_from_project_override(self, on_change_trigger): - if self._override_state is not OverrideState.PROJECT: - return - self._ignore_child_changes = True for child_obj in self.children: diff --git a/pype/settings/entities/list_entity.py b/pype/settings/entities/list_entity.py index 943863c3e0..2c252aa053 100644 --- a/pype/settings/entities/list_entity.py +++ b/pype/settings/entities/list_entity.py @@ -357,9 +357,7 @@ class ListEntity(EndpointEntity): on_change_trigger.append(self.on_change) - def add_to_studio_default(self): - if self._override_state is not OverrideState.STUDIO: - return + def _add_to_studio_default(self, _on_change_trigger): self._has_studio_override = True self.on_change() @@ -387,7 +385,7 @@ class ListEntity(EndpointEntity): on_change_trigger.append(self.on_change) - def add_to_project_override(self): + def _add_to_project_override(self, _on_change_trigger): self._has_project_override = True self.on_change() diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index 8070b65698..32696e7458 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -321,20 +321,20 @@ class RootEntity(BaseItemEntity): for child_obj in self.non_gui_children.values(): child_obj.discard_changes(on_change_trigger) - def add_to_studio_default(self): + def _add_to_studio_default(self, *args, **kwargs): """Implementation of abstract method only trigger children callback.""" for child_obj in self.non_gui_children.values(): - child_obj.add_to_studio_default() + child_obj.add_to_studio_default(*args, **kwargs) def _remove_from_studio_default(self, on_change_trigger): """Implementation of abstract method only trigger children callback.""" for child_obj in self.non_gui_children.values(): child_obj.remove_from_studio_default(on_change_trigger) - def add_to_project_override(self): + def _add_to_project_override(self, *args, **kwargs): """Implementation of abstract method only trigger children callback.""" for child_obj in self.non_gui_children.values(): - child_obj.add_to_project_override() + child_obj.add_to_project_override(*args, **kwargs) def _remove_from_project_override(self, on_change_trigger): """Implementation of abstract method only trigger children callback.""" From 26d9017831614b83e9c20b22ada448c05127a49b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 15:49:52 +0100 Subject: [PATCH 66/83] fix add to project override validaiton --- pype/settings/entities/base_entity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/settings/entities/base_entity.py b/pype/settings/entities/base_entity.py index 187e1abb60..b2be6819d5 100644 --- a/pype/settings/entities/base_entity.py +++ b/pype/settings/entities/base_entity.py @@ -481,7 +481,7 @@ class BaseItemEntity(BaseEntity): return False # Skip if already is marked to save project overrides - if self.is_group and self.has_studio_override: + if self.is_group and self.has_project_override: return False return True From c2e7e1b4507ece244963e0e57c3dfc51dd18ac3e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 16:07:51 +0100 Subject: [PATCH 67/83] mutable dict empty row visibility fix --- .../tools/settings/settings/widgets/dict_mutable_widget.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pype/tools/settings/settings/widgets/dict_mutable_widget.py b/pype/tools/settings/settings/widgets/dict_mutable_widget.py index 337aa661cf..ed89ecc6c6 100644 --- a/pype/tools/settings/settings/widgets/dict_mutable_widget.py +++ b/pype/tools/settings/settings/widgets/dict_mutable_widget.py @@ -768,6 +768,7 @@ class DictMutableKeysWidget(BaseWidget): self.update_style() def _on_entity_change(self): + changed = False to_remove = [] for input_field in self.input_fields: found = False @@ -780,6 +781,7 @@ class DictMutableKeysWidget(BaseWidget): to_remove.append(input_field) for input_field in to_remove: + changed = True self.remove_row(input_field) for key, child_entity in self.entity.items(): @@ -793,6 +795,7 @@ class DictMutableKeysWidget(BaseWidget): break if not found: + changed = True args = [previous_input] if previous_input is None: args.append(True) @@ -804,8 +807,12 @@ class DictMutableKeysWidget(BaseWidget): else: if input_field.key_value() != key: + changed = True input_field.set_key(key) + if changed: + self.on_shuffle() + def set_entity_value(self): while self.input_fields: self.remove_row(self.input_fields[0]) From 59c74f5c23fa766691ca380809628f19d2ac075a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 16:24:38 +0100 Subject: [PATCH 68/83] fixed list item adding and order --- .../settings/widgets/list_item_widget.py | 49 +++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/pype/tools/settings/settings/widgets/list_item_widget.py b/pype/tools/settings/settings/widgets/list_item_widget.py index a7f3438987..5171942781 100644 --- a/pype/tools/settings/settings/widgets/list_item_widget.py +++ b/pype/tools/settings/settings/widgets/list_item_widget.py @@ -263,36 +263,35 @@ class ListWidget(InputWidget): def _on_entity_change(self): # TODO do less inefficient - current_entities = [] - for input_field in self.input_fields: - current_entities.append(input_field.entity) - - for idx, child_entity in enumerate(self.entity): - found = False - for input_field in self.input_fields: - if input_field.entity is child_entity: - found = True - break - - if not found: - self.add_row(child_entity, idx) - + input_field_last_idx = len(self.input_fields) - 1 child_len = len(self.entity) - for idx, child_entity in enumerate(tuple(self.entity)): + for idx, child_entity in enumerate(self.entity): + if idx > input_field_last_idx: + self.add_row(child_entity, idx) + input_field_last_idx += 1 + continue + if self.input_fields[idx].entity is child_entity: continue - for _idx in range(idx, child_len): - input_field = self.input_fields[_idx] - if input_field.entity is not child_entity: - continue + input_field_idx = None + for _input_field_idx, input_field in enumerate(self.input_fields): + if input_field.entity is child_entity: + input_field_idx = _input_field_idx + break - self.content_layout.insertWidget(idx, input_field) - break + if input_field_idx is None: + self.add_row(child_entity, idx) + input_field_last_idx += 1 + continue - input_field_len = len(self.input_fields) - if child_len != input_field_len: - for _idx in range(child_len, input_field_len): + input_field = self.input_fields.pop(input_field_idx) + self.input_fields.insert(idx, input_field) + self.content_layout.insertWidget(idx, input_field) + + new_input_field_len = len(self.input_fields) + if child_len != new_input_field_len: + for _idx in range(child_len, new_input_field_len): # Remove row at the same index self.remove_row(self.input_fields[child_len]) @@ -348,7 +347,7 @@ class ListWidget(InputWidget): if row < max_index: next_field = self.input_fields[row] - self.content_layout.insertWidget(row, item_widget) + self.content_layout.insertWidget(row + 1, item_widget) self.input_fields.insert(row, item_widget) if previous_field: From 0aed03dd79632d283502d2602b4842f97f39de58 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 16:34:20 +0100 Subject: [PATCH 69/83] added swapping to list entity --- pype/settings/entities/list_entity.py | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/pype/settings/entities/list_entity.py b/pype/settings/entities/list_entity.py index 2c252aa053..48e9c132e4 100644 --- a/pype/settings/entities/list_entity.py +++ b/pype/settings/entities/list_entity.py @@ -36,6 +36,19 @@ class ListEntity(EndpointEntity): return True return False + def index(self, item): + if isinstance(item, BaseEntity): + for idx, child_entity in enumerate(self.children): + if child_entity.id == item.id: + return idx + else: + for idx, _item in enumerate(self.value): + if item == _item: + return idx + raise ValueError( + "{} is not in {}".format(item, self.__class__.__name__) + ) + def append(self, item): child_obj = self._add_new_item() child_obj.set_override_state(self._override_state) @@ -89,6 +102,22 @@ class ListEntity(EndpointEntity): self.on_change() return child_obj + def swap_items(self, item_1, item_2): + index_1 = self.index(item_1) + index_2 = self.index(item_2) + self.swap_indexes(index_1, index_2) + + def swap_indexes(self, index_1, index_2): + children_len = len(self.children) + if index_1 > children_len or index_2 > children_len: + raise IndexError( + "{} index out of range".format(self.__class__.__name__) + ) + self.children[index_1], self.children[index_2] = ( + self.children[index_2], self.children[index_1] + ) + self.on_change() + def _item_initalization(self): self.valid_value_types = (list, ) self.children = [] From a25946e67791f4406a62bd75237433d02990b696 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 16:34:39 +0100 Subject: [PATCH 70/83] list widget does not swap only trigger swapping on entity --- pype/settings/entities/input_entities.py | 3 --- .../settings/settings/widgets/list_item_widget.py | 15 +-------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/pype/settings/entities/input_entities.py b/pype/settings/entities/input_entities.py index 0f9f5c8a36..fa78931a05 100644 --- a/pype/settings/entities/input_entities.py +++ b/pype/settings/entities/input_entities.py @@ -243,9 +243,6 @@ class InputEntity(EndpointEntity): self._current_value = copy.deepcopy(value) def _discard_changes(self, on_change_trigger=None): - if self._override_state is OverrideState.NOT_DEFINED: - return - self._value_is_modified = False if self._override_state >= OverrideState.PROJECT: self._has_project_override = self.had_project_override diff --git a/pype/tools/settings/settings/widgets/list_item_widget.py b/pype/tools/settings/settings/widgets/list_item_widget.py index 5171942781..699669abab 100644 --- a/pype/tools/settings/settings/widgets/list_item_widget.py +++ b/pype/tools/settings/settings/widgets/list_item_widget.py @@ -304,20 +304,7 @@ class ListWidget(InputWidget): if row_1 == row_2: return - if row_1 > row_2: - row_1, row_2 = row_2, row_1 - - field_1 = self.input_fields[row_1] - field_2 = self.input_fields[row_2] - - self.input_fields[row_1] = field_2 - self.input_fields[row_2] = field_1 - - layout_index = self.content_layout.indexOf(field_1) - self.content_layout.insertWidget(layout_index + 1, field_1) - - field_1.order_changed() - field_2.order_changed() + self.entity.swap_indexes(row_1, row_2) def add_new_item(self, row=None): new_entity = self.entity.add_new_item(row) From a5cd19c863e779ceb25a67fe2d6a137d75125eaa Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 17:41:55 +0100 Subject: [PATCH 71/83] modified settings value check --- pype/settings/entities/input_entities.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/settings/entities/input_entities.py b/pype/settings/entities/input_entities.py index fa78931a05..17aa13bb08 100644 --- a/pype/settings/entities/input_entities.py +++ b/pype/settings/entities/input_entities.py @@ -52,10 +52,10 @@ class EndpointEntity(ItemEntity): if self.is_group: if self._override_state is OverrideState.STUDIO: - if not self._has_studio_override: + if not self.has_studio_override: return NOT_SET elif self._override_state is OverrideState.PROJECT: - if not self._has_project_override: + if not self.has_project_override: return NOT_SET return self._settings_value() From a1845d61b89f99aeb7a7532c45ed570a8480d088 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 17:42:45 +0100 Subject: [PATCH 72/83] added `_on_key_change` to mutable dict item --- .../entities/dict_mutable_keys_entity.py | 48 ++++++++++++++----- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index f8c86a3159..88707ce00d 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -87,6 +87,27 @@ class DictMutableKeysEntity(EndpointEntity): if new_key == old_key: return self.children_by_key[new_key] = self.children_by_key.pop(old_key) + self._on_key_change() + + def _on_key_change(self): + key_changed = False + for key, child_id in self.initial_child_id_by_key.items(): + child_entity = self.children_by_key.get(key) + if child_entity is None: + key_changed = True + break + + if child_entity.id != child_id: + key_changed = True + break + + if not key_changed: + return + + if self._override_state is OverrideState.STUDIO: + self._has_studio_override = True + elif self._override_state is OverrideState.PROJECT: + self._has_project_override = True self.on_change() def _add_key(self, key): @@ -146,6 +167,7 @@ class DictMutableKeysEntity(EndpointEntity): self._project_override_metadata = {} self.initial_value = None + self.initial_child_id_by_key = {} self._ignore_child_changes = False @@ -217,10 +239,6 @@ class DictMutableKeysEntity(EndpointEntity): if self._ignore_child_changes: return - if self._override_state is OverrideState.STUDIO: - self._has_studio_override = self._child_has_studio_override - elif self._override_state is OverrideState.PROJECT: - self._has_project_override = self._child_has_project_override self.on_change() def _metadata_for_current_state(self): @@ -287,27 +305,30 @@ class DictMutableKeysEntity(EndpointEntity): # Simulate `clear` method without triggering value change for key in tuple(self.children_by_key.keys()): - child_obj = self.children_by_key.pop(key) + self.children_by_key.pop(key) # Create new children children_label_by_id = {} + initial_child_id_by_key = {} metadata_labels = metadata.get(M_DYNAMIC_KEY_LABEL) or {} for _key, _value in new_value.items(): - child_obj = self._add_key(_key) - child_obj.update_default_value(_value) + child_entity = self._add_key(_key) + child_entity.update_default_value(_value) if using_project_overrides: - child_obj.update_project_value(_value) + child_entity.update_project_value(_value) elif using_studio_overrides: - child_obj.update_studio_value(_value) + child_entity.update_studio_value(_value) label = metadata_labels.get(_key) if label: - children_label_by_id[child_obj.id] = label - child_obj.set_override_state(state) + children_label_by_id[child_entity.id] = label + initial_child_id_by_key[_key] = child_entity.id + child_entity.set_override_state(state) self.children_label_by_id = children_label_by_id self.initial_value = self.settings_value() + self.initial_child_id_by_key = initial_child_id_by_key def children_key_by_id(self): return { @@ -331,8 +352,9 @@ class DictMutableKeysEntity(EndpointEntity): children_key_by_id = self.children_key_by_id() label_metadata = {} for child_id, label in self.children_label_by_id.items(): - key = children_key_by_id[child_id] - label_metadata[key] = label + key = children_key_by_id.get(child_id) + if key: + label_metadata[key] = label output[M_DYNAMIC_KEY_LABEL] = label_metadata From d4e0a387073a1d272ac77641b06452fee617c5e6 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 17:44:59 +0100 Subject: [PATCH 73/83] disable project list when defaults are not set --- pype/tools/settings/settings/widgets/categories.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index 48041bd607..f41f2eb7ec 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -437,6 +437,7 @@ class ProjectWidget(SettingsCategoryWidget): if self.modify_defaults_checkbox: self.modify_defaults_checkbox.setEnabled(True) + self.project_list_widget.setEnabled(True) except DefaultsNotDefined: if not self.modify_defaults_checkbox: @@ -450,6 +451,7 @@ class ProjectWidget(SettingsCategoryWidget): self.entity.set_defaults_state() self.modify_defaults_checkbox.setChecked(True) self.modify_defaults_checkbox.setEnabled(False) + self.project_list_widget.setEnabled(False) def _on_project_change(self): project_name = self.project_list_widget.project_name() From d437463b48e94d7755cbd6f831ca175d6dc0add0 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 17:55:37 +0100 Subject: [PATCH 74/83] raise exception when tried to change to project overrides when studio overrides are not fully saved --- pype/settings/entities/__init__.py | 2 ++ .../entities/dict_mutable_keys_entity.py | 18 +++++++++++++----- pype/settings/entities/exceptions.py | 8 ++++++++ pype/settings/entities/input_entities.py | 19 ++++++++++++++----- pype/settings/entities/item_entities.py | 18 +++++++++++++----- pype/settings/entities/list_entity.py | 18 +++++++++++++----- .../settings/settings/widgets/categories.py | 6 +++++- .../settings/settings/widgets/widgets.py | 3 +++ 8 files changed, 71 insertions(+), 21 deletions(-) diff --git a/pype/settings/entities/__init__.py b/pype/settings/entities/__init__.py index fbc08ca51d..a3cf7c7a54 100644 --- a/pype/settings/entities/__init__.py +++ b/pype/settings/entities/__init__.py @@ -55,6 +55,7 @@ print(system_settings["general"]["studio_name"].value) from .exceptions import ( DefaultsNotDefined, + StudioDefaultsNotDefined, InvalidValueType, SchemaMissingFileInfo, SchemeGroupHierarchyBug, @@ -107,6 +108,7 @@ from .anatomy_entities import ( __all__ = ( "DefaultsNotDefined", + "StudioDefaultsNotDefined", "InvalidValueType", "SchemaMissingFileInfo", "SchemeGroupHierarchyBug", diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index 88707ce00d..435bad7678 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -5,7 +5,10 @@ from .lib import ( OverrideState ) from . import EndpointEntity -from .exceptions import DefaultsNotDefined +from .exceptions import ( + DefaultsNotDefined, + StudioDefaultsNotDefined +) from pype.settings.constants import ( METADATA_KEYS, M_DYNAMIC_KEY_LABEL, @@ -264,10 +267,15 @@ class DictMutableKeysEntity(EndpointEntity): # TODO change metadata self._override_state = state - if not self.has_default_value and state > OverrideState.DEFAULTS: - # Ignore if is dynamic item and use default in that case - if not self.is_dynamic_item and not self.is_in_dynamic_item: - raise DefaultsNotDefined(self) + # Ignore if is dynamic item and use default in that case + if not self.is_dynamic_item and not self.is_in_dynamic_item: + if state > OverrideState.DEFAULTS: + if not self.has_default_value: + raise DefaultsNotDefined(self) + + elif state > OverrideState.STUDIO: + if not self.had_studio_override: + raise StudioDefaultsNotDefined(self) if state is OverrideState.STUDIO: self._has_studio_override = self.had_studio_override diff --git a/pype/settings/entities/exceptions.py b/pype/settings/entities/exceptions.py index 1d5624c967..951cd07243 100644 --- a/pype/settings/entities/exceptions.py +++ b/pype/settings/entities/exceptions.py @@ -4,6 +4,14 @@ class DefaultsNotDefined(Exception): super(DefaultsNotDefined, self).__init__(msg) +class StudioDefaultsNotDefined(Exception): + def __init__(self, obj): + msg = "Studio default values for object are not set. {}".format( + obj.path + ) + super(StudioDefaultsNotDefined, self).__init__(msg) + + class InvalidValueType(Exception): msg_template = "{}" diff --git a/pype/settings/entities/input_entities.py b/pype/settings/entities/input_entities.py index 17aa13bb08..0eaafb6c25 100644 --- a/pype/settings/entities/input_entities.py +++ b/pype/settings/entities/input_entities.py @@ -6,7 +6,11 @@ from .lib import ( NOT_SET, OverrideState ) -from .exceptions import DefaultsNotDefined +from .exceptions import ( + DefaultsNotDefined, + StudioDefaultsNotDefined +) + from pype.settings.constants import ( METADATA_KEYS, M_ENVIRONMENT_KEY @@ -207,10 +211,15 @@ class InputEntity(EndpointEntity): return self._override_state = state - if not self.has_default_value and state > OverrideState.DEFAULTS: - # Ignore if is dynamic item and use default in that case - if not self.is_dynamic_item and not self.is_in_dynamic_item: - raise DefaultsNotDefined(self) + # Ignore if is dynamic item and use default in that case + if not self.is_dynamic_item and not self.is_in_dynamic_item: + if state > OverrideState.DEFAULTS: + if not self.has_default_value: + raise DefaultsNotDefined(self) + + elif state > OverrideState.STUDIO: + if not self.had_studio_override: + raise StudioDefaultsNotDefined(self) if state is OverrideState.STUDIO: self._has_studio_override = ( diff --git a/pype/settings/entities/item_entities.py b/pype/settings/entities/item_entities.py index 30be845d60..5986d685d6 100644 --- a/pype/settings/entities/item_entities.py +++ b/pype/settings/entities/item_entities.py @@ -2,7 +2,10 @@ from .lib import ( NOT_SET, OverrideState ) -from .exceptions import DefaultsNotDefined +from .exceptions import ( + DefaultsNotDefined, + StudioDefaultsNotDefined +) from .base_entity import ItemEntity @@ -345,10 +348,15 @@ class ListStrictEntity(ItemEntity): return self._override_state = state - if not self.has_default_value and state > OverrideState.DEFAULTS: - # Ignore if is dynamic item and use default in that case - if not self.is_dynamic_item and not self.is_in_dynamic_item: - raise DefaultsNotDefined(self) + # Ignore if is dynamic item and use default in that case + if not self.is_dynamic_item and not self.is_in_dynamic_item: + if state > OverrideState.DEFAULTS: + if not self.has_default_value: + raise DefaultsNotDefined(self) + + elif state > OverrideState.STUDIO: + if not self.had_studio_override: + raise StudioDefaultsNotDefined(self) for child_entity in self.children: child_entity.set_override_state(state) diff --git a/pype/settings/entities/list_entity.py b/pype/settings/entities/list_entity.py index 48e9c132e4..be42d847cf 100644 --- a/pype/settings/entities/list_entity.py +++ b/pype/settings/entities/list_entity.py @@ -7,7 +7,10 @@ from .lib import ( NOT_SET, OverrideState ) -from .exceptions import DefaultsNotDefined +from .exceptions import ( + DefaultsNotDefined, + StudioDefaultsNotDefined +) class ListEntity(EndpointEntity): @@ -200,10 +203,15 @@ class ListEntity(EndpointEntity): while self.children: self.children.pop(0) - if not self.has_default_value and state > OverrideState.DEFAULTS: - # Ignore if is dynamic item and use default in that case - if not self.is_dynamic_item and not self.is_in_dynamic_item: - raise DefaultsNotDefined(self) + # Ignore if is dynamic item and use default in that case + if not self.is_dynamic_item and not self.is_in_dynamic_item: + if state > OverrideState.DEFAULTS: + if not self.has_default_value: + raise DefaultsNotDefined(self) + + elif state > OverrideState.STUDIO: + if not self.had_studio_override: + raise StudioDefaultsNotDefined(self) value = NOT_SET if self._override_state is OverrideState.PROJECT: diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index f41f2eb7ec..dacc587f7d 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -20,7 +20,8 @@ from pype.settings.entities import ( PathInput, RawJsonEntity, - DefaultsNotDefined + DefaultsNotDefined, + StudioDefaultsNotDefined ) from pype.settings.lib import get_system_settings @@ -453,6 +454,9 @@ class ProjectWidget(SettingsCategoryWidget): self.modify_defaults_checkbox.setEnabled(False) self.project_list_widget.setEnabled(False) + except StudioDefaultsNotDefined: + self.select_default_project() + def _on_project_change(self): project_name = self.project_list_widget.project_name() if project_name == self.project_name: diff --git a/pype/tools/settings/settings/widgets/widgets.py b/pype/tools/settings/settings/widgets/widgets.py index ad0895758f..fd8d9d753c 100644 --- a/pype/tools/settings/settings/widgets/widgets.py +++ b/pype/tools/settings/settings/widgets/widgets.py @@ -617,6 +617,9 @@ class ProjectListWidget(QtWidgets.QWidget): return None return self.current_project + def select_default_project(self): + self.select_project(self.default) + def select_project(self, project_name): model = self.project_list.model() found_items = model.findItems(project_name) From 2716233e1f5317b48b7a22e105e37150adb4412c Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 17:58:16 +0100 Subject: [PATCH 75/83] always change overrides attribute on child change in list and modifiable dict --- pype/settings/entities/dict_mutable_keys_entity.py | 5 +++++ pype/settings/entities/list_entity.py | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index 435bad7678..9325aeab09 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -242,6 +242,11 @@ class DictMutableKeysEntity(EndpointEntity): if self._ignore_child_changes: return + if self._override_state is OverrideState.STUDIO: + self._has_studio_override = True + elif self._override_state is OverrideState.PROJECT: + self._has_project_override = True + self.on_change() def _metadata_for_current_state(self): diff --git a/pype/settings/entities/list_entity.py b/pype/settings/entities/list_entity.py index be42d847cf..07221929b7 100644 --- a/pype/settings/entities/list_entity.py +++ b/pype/settings/entities/list_entity.py @@ -185,11 +185,10 @@ class ListEntity(EndpointEntity): if self._ignore_child_changes: return - # TODO is this enough? if self._override_state is OverrideState.STUDIO: - self._has_studio_override = self._child_has_studio_override + self._has_studio_override = True elif self._override_state is OverrideState.PROJECT: - self._has_project_override = self._child_has_project_override + self._has_project_override = True self.on_change() def set_override_state(self, state): From af642c6762bf15d5ed8584b955c2eba6843c979a Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 18:00:21 +0100 Subject: [PATCH 76/83] simplified key change --- .../entities/dict_mutable_keys_entity.py | 24 +++---------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index 9325aeab09..ce97895a44 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -90,23 +90,9 @@ class DictMutableKeysEntity(EndpointEntity): if new_key == old_key: return self.children_by_key[new_key] = self.children_by_key.pop(old_key) - self._on_key_change() - - def _on_key_change(self): - key_changed = False - for key, child_id in self.initial_child_id_by_key.items(): - child_entity = self.children_by_key.get(key) - if child_entity is None: - key_changed = True - break - - if child_entity.id != child_id: - key_changed = True - break - - if not key_changed: - return + self._on_key_label_change() + def _on_key_label_change(self): if self._override_state is OverrideState.STUDIO: self._has_studio_override = True elif self._override_state is OverrideState.PROJECT: @@ -154,7 +140,7 @@ class DictMutableKeysEntity(EndpointEntity): def set_child_label(self, child_entity, label): self.children_label_by_id[child_entity.id] = label - self.on_change() + self._on_key_label_change() def get_key_label(self, key): child_entity = self.children_by_key[key] @@ -170,7 +156,6 @@ class DictMutableKeysEntity(EndpointEntity): self._project_override_metadata = {} self.initial_value = None - self.initial_child_id_by_key = {} self._ignore_child_changes = False @@ -322,7 +307,6 @@ class DictMutableKeysEntity(EndpointEntity): # Create new children children_label_by_id = {} - initial_child_id_by_key = {} metadata_labels = metadata.get(M_DYNAMIC_KEY_LABEL) or {} for _key, _value in new_value.items(): child_entity = self._add_key(_key) @@ -335,13 +319,11 @@ class DictMutableKeysEntity(EndpointEntity): label = metadata_labels.get(_key) if label: children_label_by_id[child_entity.id] = label - initial_child_id_by_key[_key] = child_entity.id child_entity.set_override_state(state) self.children_label_by_id = children_label_by_id self.initial_value = self.settings_value() - self.initial_child_id_by_key = initial_child_id_by_key def children_key_by_id(self): return { From c8d132fd06f5c8cf4beffec66841754d3acdcefe Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 18:31:48 +0100 Subject: [PATCH 77/83] label changes should work now --- .../settings/widgets/dict_mutable_widget.py | 54 ++++++++++++------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/pype/tools/settings/settings/widgets/dict_mutable_widget.py b/pype/tools/settings/settings/widgets/dict_mutable_widget.py index ed89ecc6c6..b27e0e492b 100644 --- a/pype/tools/settings/settings/widgets/dict_mutable_widget.py +++ b/pype/tools/settings/settings/widgets/dict_mutable_widget.py @@ -13,8 +13,6 @@ from .lib import ( CHILD_OFFSET ) -from pype.settings.entities import NOT_SET - def create_add_btn(parent): add_btn = QtWidgets.QPushButton("+", parent) @@ -161,8 +159,8 @@ class ModifiableDictItem(QtWidgets.QWidget): self.is_key_duplicated = False self.is_required = False - self.origin_key = NOT_SET - self.origin_key_label = NOT_SET + self.origin_key = None + self.origin_key_label = None self.temp_key = "" self.uuid_key = None @@ -171,6 +169,8 @@ class ModifiableDictItem(QtWidgets.QWidget): self.wrapper_widget = None + self.key_label_input = None + if collapsible_key: self.create_collapsible_ui() else: @@ -272,7 +272,7 @@ class ModifiableDictItem(QtWidgets.QWidget): key_input.textChanged.connect(self._on_key_change) key_input.returnPressed.connect(self._on_enter_press) - key_label_input.textChanged.connect(self._on_key_change) + key_label_input.textChanged.connect(self._on_key_label_change) key_label_input.returnPressed.connect(self._on_enter_press) edit_btn.clicked.connect(self.on_edit_pressed) @@ -339,10 +339,13 @@ class ModifiableDictItem(QtWidgets.QWidget): def set_key_label(self, key, label): self.set_key(key) - if label: - self.key_label_input.setText(label) + self.set_label(label) self.set_edit_mode(False) + def set_label(self, label): + if self.key_label_input and label is not None: + self.key_label_input.setText(label) + def set_as_required(self, key): self.key_input.setText(key) self.key_input.setEnabled(False) @@ -372,6 +375,8 @@ class ModifiableDictItem(QtWidgets.QWidget): self.set_edit_mode(False) def _on_key_label_change(self): + label = self.key_label_value() + self.entity_widget.change_label(label, self) self.update_key_label() def _on_key_change(self): @@ -439,17 +444,6 @@ class ModifiableDictItem(QtWidgets.QWidget): def is_key_label_modified(self): return self.key_label_value() != self.origin_key_label - def is_value_modified(self): - return self.input_field.is_modified - - @property - def is_modified(self): - return ( - self.is_key_modified() - or self.is_key_label_modified() - or self.is_value_modified() - ) - def trigger_hierarchical_style_update(self): self.entity_widget.trigger_hierarchical_style_update() @@ -516,9 +510,9 @@ class ModifiableDictItem(QtWidgets.QWidget): return self.entity_widget.input_fields.index(self) def key_label_value(self): - if self.collapsible_key: + if self.key_label_input: return self.key_label_input.text() - return NOT_SET + return None def mouseReleaseEvent(self, event): return QtWidgets.QWidget.mouseReleaseEvent(self, event) @@ -697,6 +691,13 @@ class DictMutableKeysWidget(BaseWidget): self.entity.children_by_key[sk_old_key] ) + def change_label(self, label, input_field): + entity = input_field.entity + _label = self.entity.get_child_label(entity) + if _label == label: + return + self.entity.set_child_label(entity, label) + def add_widget_for_child( self, child_entity, after_widget=None, first=False ): @@ -803,6 +804,10 @@ class DictMutableKeysWidget(BaseWidget): _input_field = self.add_widget_for_child(child_entity, *args) _input_field.origin_key = key _input_field.set_key(key) + if self.entity.collapsible_key: + label = self.entity.get_child_label(child_entity) + _input_field.origin_key_label = label + _input_field.set_label(label) _input_field.set_entity_value() else: @@ -810,6 +815,11 @@ class DictMutableKeysWidget(BaseWidget): changed = True input_field.set_key(key) + if self.entity.collapsible_key: + label = self.entity.get_child_label(child_entity) + if input_field.key_label_value() != label: + input_field.set_label(label) + if changed: self.on_shuffle() @@ -821,6 +831,10 @@ class DictMutableKeysWidget(BaseWidget): input_field = self.add_widget_for_child(child_entity) input_field.origin_key = key input_field.set_key(key) + if self.entity.collapsible_key: + label = self.entity.get_child_label(child_entity) + input_field.origin_key_label = label + input_field.set_label(label) for input_field in self.input_fields: input_field.set_entity_value() From bd55312fbc4296f6464b6cc2d2f381bf4ece2c7e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 17 Feb 2021 18:55:04 +0100 Subject: [PATCH 78/83] anatomy templates and roots see each other's overrides --- pype/settings/entities/__init__.py | 6 +- pype/settings/entities/anatomy_entities.py | 92 +++++++++++++++++++ .../schemas/schema_anatomy_templates.json | 2 +- 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/pype/settings/entities/__init__.py b/pype/settings/entities/__init__.py index a3cf7c7a54..f67286832c 100644 --- a/pype/settings/entities/__init__.py +++ b/pype/settings/entities/__init__.py @@ -102,7 +102,8 @@ from .dict_mutable_keys_entity import DictMutableKeysEntity from .anatomy_entities import ( AnatomyEntity, - AnatomyRootsEntity + AnatomyRootsEntity, + AnatomyTemplatesEntity ) @@ -147,5 +148,6 @@ __all__ = ( "DictMutableKeysEntity", "AnatomyEntity", - "AnatomyRootsEntity" + "AnatomyRootsEntity", + "AnatomyTemplatesEntity" ) diff --git a/pype/settings/entities/anatomy_entities.py b/pype/settings/entities/anatomy_entities.py index f89318e213..1b98bda4dd 100644 --- a/pype/settings/entities/anatomy_entities.py +++ b/pype/settings/entities/anatomy_entities.py @@ -5,6 +5,98 @@ from .dict_mutable_keys_entity import DictMutableKeysEntity class AnatomyEntity(DictImmutableKeysEntity): schema_types = ["anatomy"] + def _item_initalization(self): + self._roots_entity = None + self._templates_entity = None + + super(AnatomyEntity, self)._item_initalization() + + @property + def roots_entity(self): + if self._roots_entity is None: + _roots_entity = None + for child_entity in self.non_gui_children.values(): + if isinstance(child_entity, AnatomyRootsEntity): + _roots_entity = child_entity + break + + if _roots_entity is None: + raise KeyError( + "AnatomyEntity does not contain AnatomyRootsEntity" + ) + + self._roots_entity = _roots_entity + return self._roots_entity + + @property + def templates_entity(self): + if self._templates_entity is None: + _templates_entity = None + for child_entity in self.non_gui_children.values(): + if isinstance(child_entity, AnatomyTemplatesEntity): + _templates_entity = child_entity + break + + if _templates_entity is None: + raise KeyError( + "AnatomyEntity does not contain AnatomyRootsEntity" + ) + + self._templates_entity = _templates_entity + return self._templates_entity + class AnatomyRootsEntity(DictMutableKeysEntity): schema_types = ["anatomy_roots"] + + def schema_validations(self): + if not isinstance(self.parent, AnatomyEntity): + raise TypeError("Parent of {} is not AnatomyEntity object".format( + self.__class__.__name__ + )) + super(AnatomyRootsEntity, self).schema_validations() + + @property + def has_studio_override(self): + output = super(AnatomyRootsEntity, self).has_studio_override + if not output: + output = self.parent.templates_entity._child_has_studio_override + return output + + @property + def has_project_override(self): + output = super(AnatomyRootsEntity, self).has_project_override + if not output: + output = self.parent.templates_entity._child_has_project_override + return output + + +class AnatomyTemplatesEntity(DictImmutableKeysEntity): + schema_types = ["anatomy_templates"] + + def schema_validations(self): + if not isinstance(self.parent, AnatomyEntity): + raise TypeError("Parent of {} is not AnatomyEntity object".format( + self.__class__.__name__ + )) + super(AnatomyTemplatesEntity, self).schema_validations() + + @property + def has_studio_override(self): + output = super(AnatomyTemplatesEntity, self).has_studio_override + if not output: + output = ( + self.parent.roots_entity._has_studio_override + or self.parent.roots_entity._child_has_studio_override + ) + return output + + @property + def has_project_override(self): + output = super(AnatomyTemplatesEntity, self).has_project_override + if not output: + output = ( + self.parent.roots_entity._has_project_override + or self.parent.roots_entity._child_has_project_override + ) + return output diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json index cffb760374..076250961e 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json @@ -1,5 +1,5 @@ { - "type": "dict", + "type": "anatomy_templates", "key": "templates", "label": "Templates", "collapsable": true, From 4df080190d0e01818e7285426222d7b9751d662e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 18 Feb 2021 10:02:27 +0100 Subject: [PATCH 79/83] removed unused import --- pype/tools/settings/settings/widgets/categories.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index dacc587f7d..a471775a57 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -25,10 +25,8 @@ from pype.settings.entities import ( ) from pype.settings.lib import get_system_settings -from .widgets import ( - UnsavedChangesDialog, - ProjectListWidget -) +from .widgets import ProjectListWidget + from . import lib from .base import GUIWidget From 1e0fbbfbbf2994057a0407bb8968596696a16fac Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 18 Feb 2021 10:17:31 +0100 Subject: [PATCH 80/83] replaced `collapsable` with `collapsible` --- .../entities/dict_immutable_keys_entity.py | 2 +- .../entities/dict_mutable_keys_entity.py | 4 ++-- pype/settings/entities/schemas/README.md | 10 ++++---- .../projects_schema/schema_plugins.json | 10 ++++---- .../schema_project_celaction.json | 6 ++--- .../schema_project_ftrack.json | 8 +++---- .../schema_project_global.json | 2 +- .../schema_project_harmony.json | 6 ++--- .../projects_schema/schema_project_hiero.json | 20 ++++++++-------- .../projects_schema/schema_project_maya.json | 2 +- .../projects_schema/schema_project_nuke.json | 24 +++++++++---------- .../schema_project_resolve.json | 14 +++++------ .../schema_project_standalonepublisher.json | 12 +++++----- .../schema_project_syncserver.json | 8 +++---- .../schema_project_unreal.json | 4 ++-- .../schemas/schema_anatomy_attributes.json | 2 +- .../schemas/schema_anatomy_imageio.json | 10 ++++---- .../schemas/schema_anatomy_templates.json | 4 ++-- .../schemas/schema_global_publish.json | 18 +++++++------- .../schemas/schema_global_tools.json | 10 ++++---- .../schemas/schema_maya_capture.json | 6 ++--- .../schemas/schema_maya_load.json | 4 ++-- .../schemas/schema_maya_publish.json | 20 ++++++++-------- .../schemas/schema_publish_gui_filter.json | 2 +- .../schemas/schema_workfile_build.json | 2 +- .../schemas/system_schema/example_schema.json | 18 +++++++------- .../host_settings/schema_aftereffects.json | 2 +- .../host_settings/schema_blender.json | 2 +- .../host_settings/schema_celaction.json | 2 +- .../host_settings/schema_djv.json | 2 +- .../host_settings/schema_fusion.json | 2 +- .../host_settings/schema_harmony.json | 2 +- .../host_settings/schema_houdini.json | 2 +- .../host_settings/schema_maya.json | 2 +- .../host_settings/schema_mayabatch.json | 2 +- .../host_settings/schema_photoshop.json | 2 +- .../host_settings/schema_resolve.json | 2 +- .../host_settings/schema_shell.json | 2 +- .../host_settings/schema_tvpaint.json | 2 +- .../host_settings/schema_unreal.json | 2 +- .../host_settings/template_host_variant.json | 2 +- .../host_settings/template_nuke.json | 2 +- .../module_settings/schema_ftrack.json | 4 ++-- .../system_schema/schema_applications.json | 2 +- .../schemas/system_schema/schema_general.json | 2 +- .../schemas/system_schema/schema_modules.json | 24 +++++++++---------- .../schemas/system_schema/schema_tools.json | 2 +- .../tool_settings/schema_arnold.json | 2 +- .../tool_settings/schema_vray.json | 2 +- .../tool_settings/schema_yeti.json | 2 +- pype/tools/settings/settings/README.md | 10 ++++---- .../settings/widgets/wrapper_widgets.py | 2 +- 52 files changed, 156 insertions(+), 156 deletions(-) diff --git a/pype/settings/entities/dict_immutable_keys_entity.py b/pype/settings/entities/dict_immutable_keys_entity.py index c983dace2c..854c904f3c 100644 --- a/pype/settings/entities/dict_immutable_keys_entity.py +++ b/pype/settings/entities/dict_immutable_keys_entity.py @@ -169,7 +169,7 @@ class DictImmutableKeysEntity(ItemEntity): "highlight_content", False ) self.show_borders = self.schema_data.get("show_borders", True) - self.collapsible = self.schema_data.get("collapsable", True) + self.collapsible = self.schema_data.get("collapsible", True) self.collapsed = self.schema_data.get("collapsed", True) # Not yet implemented diff --git a/pype/settings/entities/dict_mutable_keys_entity.py b/pype/settings/entities/dict_mutable_keys_entity.py index ce97895a44..8fe71db2a3 100644 --- a/pype/settings/entities/dict_mutable_keys_entity.py +++ b/pype/settings/entities/dict_mutable_keys_entity.py @@ -169,12 +169,12 @@ class DictMutableKeysEntity(EndpointEntity): self.schema_data.get("value_is_env_group") or False ) self.required_keys = self.schema_data.get("required_keys") or [] - self.collapsible_key = self.schema_data.get("collapsable_key") or False + self.collapsible_key = self.schema_data.get("collapsible_key") or False # GUI attributes self.hightlight_content = ( self.schema_data.get("highlight_content") or False ) - self.collapsible = self.schema_data.get("collapsable", True) + self.collapsible = self.schema_data.get("collapsible", True) self.collapsed = self.schema_data.get("collapsed", True) object_type = self.schema_data["object_type"] diff --git a/pype/settings/entities/schemas/README.md b/pype/settings/entities/schemas/README.md index 643043b6c8..65d73a0728 100644 --- a/pype/settings/entities/schemas/README.md +++ b/pype/settings/entities/schemas/README.md @@ -126,8 +126,8 @@ - without label it is just wrap item holding `"key"` - can't have `"is_group"` key set to True as it breaks visual override showing - if `"label"` is entetered there which will be shown in GUI - - item with label can be collapsable - - that can be set with key `"collapsable"` as `True`/`False` (Default: `True`) + - item with label can be collapsible + - that can be set with key `"collapsible"` as `True`/`False` (Default: `True`) - with key `"collapsed"` as `True`/`False` can be set that is collapsed when GUI is opened (Default: `False`) - it is possible to add darker background with `"highlight_content"` (Default: `False`) - darker background has limits of maximum applies after 3-4 nested highlighted items there is not difference in the color @@ -138,7 +138,7 @@ "key": "applications", "type": "dict", "label": "Applications", - "collapsable": true, + "collapsible": true, "highlight_content": true, "is_group": true, "is_file": true, @@ -320,8 +320,8 @@ - there are 2 possible ways how to set the type: 1.) dictionary with item modifiers (`number` input has `minimum`, `maximum` and `decimals`) in that case item type must be set as value of `"type"` (example below) 2.) item type name as string without modifiers (e.g. `text`) -- this input can be collapsable - - that can be set with key `"collapsable"` as `True`/`False` (Default: `True`) +- this input can be collapsible + - that can be set with key `"collapsible"` as `True`/`False` (Default: `True`) - with key `"collapsed"` as `True`/`False` can be set that is collapsed when GUI is opened (Default: `False`) 1.) with item modifiers diff --git a/pype/settings/entities/schemas/projects_schema/schema_plugins.json b/pype/settings/entities/schemas/projects_schema/schema_plugins.json index ce90ceb881..a7ed64be17 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_plugins.json +++ b/pype/settings/entities/schemas/projects_schema/schema_plugins.json @@ -1,32 +1,32 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "plugins", "label": "Plugins", "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "standalonepublisher", "label": "Standalone Publisher", "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "publish", "label": "Publish plugins", "is_file": true, "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ExtractThumbnailSP", "label": "ExtractThumbnailSP", "is_group": true, "children": [ { "type": "dict", - "collapsable": false, + "collapsible": false, "key": "ffmpeg_args", "label": "ffmpeg_args", "children": [ diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_celaction.json b/pype/settings/entities/schemas/projects_schema/schema_project_celaction.json index 86d6141c4a..500e5b2298 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_celaction.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_celaction.json @@ -1,19 +1,19 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "celaction", "label": "CelAction", "is_file": true, "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "publish", "label": "Publish plugins", "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "ExtractCelactionDeadline", "label": "ExtractCelactionDeadline", diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json b/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json index d27e99da8a..39cd79e851 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_ftrack.json @@ -2,7 +2,7 @@ "type": "dict", "key": "ftrack", "label": "Ftrack", - "collapsable": true, + "collapsible": true, "is_file": true, "children": [ { @@ -609,14 +609,14 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "publish", "label": "Publish plugins", "is_file": true, "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "IntegrateFtrackNote", "label": "IntegrateFtrackNote", @@ -643,7 +643,7 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "ValidateFtrackAttributes", "label": "ValidateFtrackAttributes", diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_global.json b/pype/settings/entities/schemas/projects_schema/schema_project_global.json index 09aa424e57..fa5db9af88 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_global.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_global.json @@ -1,6 +1,6 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "global", "label": "Global", "is_file": true, diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_harmony.json b/pype/settings/entities/schemas/projects_schema/schema_project_harmony.json index 92ad39ac2c..5d1cbff1b8 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_harmony.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_harmony.json @@ -1,20 +1,20 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "harmony", "label": "Harmony", "is_file": true, "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "publish", "label": "Publish plugins", "children": [] }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "general", "label": "General", "children": [ diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_hiero.json b/pype/settings/entities/schemas/projects_schema/schema_project_hiero.json index b6276ccf9e..d2191a45a0 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_hiero.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_hiero.json @@ -1,19 +1,19 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "hiero", "label": "Hiero", "is_file": true, "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "create", "label": "Create plugins", "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "CreateShotClip", "label": "Create Shot Clip", "is_group": true, @@ -21,7 +21,7 @@ { "type": "collapsible-wrap", "label": "Shot Hierarchy And Rename Settings", - "collapsable": false, + "collapsible": false, "children": [ { "type": "text", @@ -53,7 +53,7 @@ { "type": "collapsible-wrap", "label": "Shot Template Keywords", - "collapsable": false, + "collapsible": false, "children": [ { "type": "text", @@ -85,7 +85,7 @@ { "type": "collapsible-wrap", "label": "Vertical Synchronization Of Attributes", - "collapsable": false, + "collapsible": false, "children": [ { "type": "boolean", @@ -97,7 +97,7 @@ { "type": "collapsible-wrap", "label": "Shot Attributes", - "collapsable": false, + "collapsible": false, "children": [ { "type": "number", @@ -122,13 +122,13 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "publish", "label": "Publish plugins", "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "CollectInstanceVersion", "label": "Collect Instance Version", @@ -143,7 +143,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "ExtractReviewCutUpVideo", "label": "Extract Review Cut Up Video", diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_maya.json b/pype/settings/entities/schemas/projects_schema/schema_project_maya.json index 069ae3c977..5ba5de1557 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_maya.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_maya.json @@ -1,6 +1,6 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "maya", "label": "Maya", "is_file": true, diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json b/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json index 7a6960bcbd..b60b548cb0 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_nuke.json @@ -1,19 +1,19 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "nuke", "label": "Nuke", "is_file": true, "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "create", "label": "Create plugins", "children": [ { "type": "dict", - "collapsable": false, + "collapsible": false, "key": "CreateWriteRender", "label": "CreateWriteRender", "is_group": true, @@ -27,7 +27,7 @@ }, { "type": "dict", - "collapsable": false, + "collapsible": false, "key": "CreateWritePrerender", "label": "CreateWritePrerender", "is_group": true, @@ -43,13 +43,13 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "publish", "label": "Publish plugins", "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "PreCollectNukeInstances", "label": "PreCollectNukeInstances", "is_group": true, @@ -63,7 +63,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "ExtractThumbnail", "label": "ExtractThumbnail", @@ -83,7 +83,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "ValidateKnobs", "label": "ValidateKnobs", @@ -103,7 +103,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "ExtractReviewDataLut", "label": "ExtractReviewDataLut", @@ -118,7 +118,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "ExtractReviewDataMov", "label": "ExtractReviewDataMov", @@ -138,7 +138,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ExtractSlateFrame", "label": "ExtractSlateFrame", "is_group": true, @@ -152,7 +152,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "NukeSubmitDeadline", "label": "NukeSubmitDeadline", "is_group": true, diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_resolve.json b/pype/settings/entities/schemas/projects_schema/schema_project_resolve.json index fb9b9b7a0a..68e405b7d7 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_resolve.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_resolve.json @@ -1,19 +1,19 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "resolve", "label": "DaVinci Resolve", "is_file": true, "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "create", "label": "Creator plugins", "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "CreateShotClip", "label": "Create Shot Clip", "is_group": true, @@ -21,7 +21,7 @@ { "type": "collapsible-wrap", "label": "Shot Hierarchy And Rename Settings", - "collapsable": false, + "collapsible": false, "children": [ { "type": "text", @@ -53,7 +53,7 @@ { "type": "collapsible-wrap", "label": "Shot Template Keywords", - "collapsable": false, + "collapsible": false, "children": [ { "type": "text", @@ -85,7 +85,7 @@ { "type": "collapsible-wrap", "label": "Vertical Synchronization Of Attributes", - "collapsable": false, + "collapsible": false, "children": [ { "type": "boolean", @@ -97,7 +97,7 @@ { "type": "collapsible-wrap", "label": "Shot Attributes", - "collapsable": false, + "collapsible": false, "children": [ { "type": "number", diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_standalonepublisher.json b/pype/settings/entities/schemas/projects_schema/schema_project_standalonepublisher.json index 40b27f766f..735b9611d2 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_standalonepublisher.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_standalonepublisher.json @@ -1,27 +1,27 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "standalonepublisher", "label": "Standalone Publisher", "is_file": true, "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "publish", "label": "Publish plugins", "is_file": true, "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ExtractThumbnailSP", "label": "ExtractThumbnailSP", "is_group": true, "children": [ { "type": "dict", - "collapsable": false, + "collapsible": false, "key": "ffmpeg_args", "label": "ffmpeg_args", "children": [ @@ -45,10 +45,10 @@ }, { "type": "dict-modifiable", - "collapsable": true, + "collapsible": true, "key": "create", "label": "Creator plugins", - "collapsable_key": true, + "collapsible_key": true, "is_file": true, "object_type": { "type": "dict", diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_syncserver.json b/pype/settings/entities/schemas/projects_schema/schema_project_syncserver.json index 396e4ca2dc..005e188b4d 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_syncserver.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_syncserver.json @@ -2,7 +2,7 @@ "type": "dict", "key": "sync_server", "label": "Sync Server (currently unused)", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "is_file": true, "children": [ @@ -15,7 +15,7 @@ "type": "dict", "key": "config", "label": "Config", - "collapsable": true, + "collapsible": true, "children": [ { @@ -46,10 +46,10 @@ ] }, { "type": "dict-modifiable", - "collapsable": true, + "collapsible": true, "key": "sites", "label": "Sites", - "collapsable_key": false, + "collapsible_key": false, "is_file": true, "object_type": { diff --git a/pype/settings/entities/schemas/projects_schema/schema_project_unreal.json b/pype/settings/entities/schemas/projects_schema/schema_project_unreal.json index 392289296a..b6e94d9d03 100644 --- a/pype/settings/entities/schemas/projects_schema/schema_project_unreal.json +++ b/pype/settings/entities/schemas/projects_schema/schema_project_unreal.json @@ -1,13 +1,13 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "unreal", "label": "Unreal Engine", "is_file": true, "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "project_setup", "label": "Project Setup", "children": [ diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json index 3e85c422e1..8925233bb8 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_attributes.json @@ -1,6 +1,6 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "attributes", "label": "Attributes", "is_file": true, diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json index 8f7d2cc283..7070e4b54f 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_imageio.json @@ -14,7 +14,7 @@ "key": "workfile", "type": "dict", "label": "Workfile", - "collapsable": false, + "collapsible": false, "children": [ { "type": "form", @@ -88,7 +88,7 @@ "key": "regexInputs", "type": "dict", "label": "Colorspace on Inputs by regex detection", - "collapsable": true, + "collapsible": true, "children": [ { "type": "list", @@ -122,7 +122,7 @@ "key": "workfile", "type": "dict", "label": "Workfile", - "collapsable": false, + "collapsible": false, "children": [ { "type": "form", @@ -219,7 +219,7 @@ "key": "nodes", "type": "dict", "label": "Nodes", - "collapsable": true, + "collapsible": true, "children": [ { "key": "requiredNodes", @@ -323,7 +323,7 @@ "key": "regexInputs", "type": "dict", "label": "Colorspace on Inputs by regex detection", - "collapsable": true, + "collapsible": true, "children": [ { "type": "list", diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json index 076250961e..05718e0bc9 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_anatomy_templates.json @@ -2,8 +2,8 @@ "type": "anatomy_templates", "key": "templates", "label": "Templates", - "collapsable": true, - "collapsable_key": true, + "collapsible": true, + "collapsible_key": true, "is_file": true, "is_group": true, "children": [ diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json index 5d17830b92..4045870a9a 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_global_publish.json @@ -1,12 +1,12 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "publish", "label": "Publish plugins", "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "IntegrateMasterVersion", "label": "IntegrateMasterVersion", @@ -21,7 +21,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "key": "ExtractJpegEXR", "label": "ExtractJpegEXR", @@ -54,7 +54,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ExtractReview", "label": "ExtractReview", "checkbox_key": "enabled", @@ -188,7 +188,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ExtractBurnin", "label": "ExtractBurnin", "checkbox_key": "enabled", @@ -201,7 +201,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "options", "label": "Burnin formating options", "children": [ @@ -268,7 +268,7 @@ "label": "Burnins", "type": "dict-modifiable", "highlight_content": true, - "collapsable": false, + "collapsible": false, "object_type": { "type": "dict", "children": [ @@ -312,7 +312,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "IntegrateAssetNew", "label": "IntegrateAssetNew", "is_group": true, @@ -326,7 +326,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ProcessSubmittedJobOnFarm", "label": "ProcessSubmittedJobOnFarm", "checkbox_key": "enabled", diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json index d89477edd1..fa49e12fb7 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_global_tools.json @@ -1,18 +1,18 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "tools", "label": "Tools", "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "creator", "label": "Creator", "children": [ { "type": "dict-modifiable", - "collapsable": false, + "collapsible": false, "key": "families_smart_select", "label": "Families smart select", "object_type": { @@ -24,7 +24,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "Workfiles", "label": "Workfiles", "children": [ @@ -62,7 +62,7 @@ }, { "type": "dict-modifiable", - "collapsable": true, + "collapsible": true, "key": "sw_folders", "label": "Extra task folders", "is_group": true, diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json index ba7cf4b525..648fca28e6 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_capture.json @@ -4,7 +4,7 @@ "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "capture", "label": "Maya Playblast settings", "is_file": true, @@ -311,7 +311,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "Viewport Options", "label": "Viewport Options", "children": [ @@ -527,7 +527,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "Camera Options", "label": "Camera Options", "children": [ diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json index 5aec3715bd..dd9d0508b4 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_load.json @@ -1,12 +1,12 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "load", "label": "Loader plugins", "children": [ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "colors", "label": "Loaded Subsets Outliner Colors", "children": [ diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json index d1de128934..0d705d3d02 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_maya_publish.json @@ -1,6 +1,6 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "publish", "label": "Publish plugins", "children": [ @@ -10,7 +10,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "CollectMayaRender", "label": "Collect Render Layers", "children": [ @@ -30,7 +30,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ValidateCameraAttributes", "label": "Validate Camera Attributes", "checkbox_key": "enabled", @@ -49,7 +49,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ValidateModelName", "label": "Validate Model Name", "checkbox_key": "enabled", @@ -79,7 +79,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ValidateAssemblyName", "label": "Validate Assembly Name", "checkbox_key": "enabled", @@ -93,7 +93,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ValidateShaderName", "label": "ValidateShaderName", "checkbox_key": "enabled", @@ -116,7 +116,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ValidateMeshHasOverlappingUVs", "label": "ValidateMeshHasOverlappingUVs", "checkbox_key": "enabled", @@ -130,7 +130,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ValidateAttributes", "label": "ValidateAttributes", "checkbox_key": "enabled", @@ -156,7 +156,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "ExtractCameraAlembic", "label": "Extract camera to Alembic", "checkbox_key": "enabled", @@ -184,7 +184,7 @@ }, { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "MayaSubmitDeadline", "label": "Submit maya job to deadline", "checkbox_key": "enabled", diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_publish_gui_filter.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_publish_gui_filter.json index efc6c1d629..1539bd0738 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_publish_gui_filter.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_publish_gui_filter.json @@ -1,6 +1,6 @@ { "type": "dict-modifiable", - "collapsable": true, + "collapsible": true, "key": "filters", "label": "Publish GUI Filters", "object_type": { diff --git a/pype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json b/pype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json index bf0aff2d41..0cb36c2f92 100644 --- a/pype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json +++ b/pype/settings/entities/schemas/projects_schema/schemas/schema_workfile_build.json @@ -1,6 +1,6 @@ { "type": "dict", - "collapsable": true, + "collapsible": true, "key": "workfile_build", "label": "Workfile Build Settings", "children": [ diff --git a/pype/settings/entities/schemas/system_schema/example_schema.json b/pype/settings/entities/schemas/system_schema/example_schema.json index 4175cebd42..c8920db88a 100644 --- a/pype/settings/entities/schemas/system_schema/example_schema.json +++ b/pype/settings/entities/schemas/system_schema/example_schema.json @@ -326,10 +326,10 @@ "multipath": true }, { - "key": "collapsable", + "key": "collapsible", "type": "dict", - "label": "collapsable dictionary", - "collapsable": true, + "label": "collapsible dictionary", + "collapsible": true, "is_group": true, "children": [ { @@ -340,10 +340,10 @@ ] }, { - "key": "collapsable_expanded", + "key": "collapsible_expanded", "type": "dict", - "label": "collapsable dictionary, expanded on creation", - "collapsable": true, + "label": "collapsible dictionary, expanded on creation", + "collapsible": true, "collapsed": false, "is_group": true, "children": [ @@ -355,10 +355,10 @@ ] }, { - "key": "not_collapsable", + "key": "not_collapsible", "type": "dict", - "label": "Not collapsable", - "collapsable": false, + "label": "Not collapsible", + "collapsible": false, "is_group": true, "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_aftereffects.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_aftereffects.json index 4578e836b5..4304c65445 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_aftereffects.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_aftereffects.json @@ -2,7 +2,7 @@ "type": "dict", "key": "aftereffects", "label": "Adobe AfterEffects", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_blender.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_blender.json index fbb9a82b87..5d8cb45da8 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_blender.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_blender.json @@ -2,7 +2,7 @@ "type": "dict", "key": "blender", "label": "Blender", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_celaction.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_celaction.json index 0578dcae9e..ab3f0f3f15 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_celaction.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_celaction.json @@ -2,7 +2,7 @@ "type": "dict", "key": "celaction", "label": "CelAction2D", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_djv.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_djv.json index 6df690d43c..02c90a92ad 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_djv.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_djv.json @@ -2,7 +2,7 @@ "type": "dict", "key": "djvview", "label": "DJV View", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json index 189588ace1..1c1b7653d9 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_fusion.json @@ -2,7 +2,7 @@ "type": "dict", "key": "fusion", "label": "Blackmagic Fusion", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_harmony.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_harmony.json index 2a042be1e3..b0abf35bfa 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_harmony.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_harmony.json @@ -2,7 +2,7 @@ "type": "dict", "key": "harmony", "label": "Toon Boom Harmony", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_houdini.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_houdini.json index 404b2bfbc7..cc0cd54cf2 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_houdini.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_houdini.json @@ -2,7 +2,7 @@ "type": "dict", "key": "houdini", "label": "SideFX Houdini", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_maya.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_maya.json index ba639ca134..84782cb3d8 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_maya.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_maya.json @@ -2,7 +2,7 @@ "type": "dict", "key": "maya", "label": "Autodesk Maya", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_mayabatch.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_mayabatch.json index cee0cd8e9f..dbd850dcd6 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_mayabatch.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_mayabatch.json @@ -2,7 +2,7 @@ "type": "dict", "key": "mayabatch", "label": "Autodesk Maya Batch", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_photoshop.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_photoshop.json index 61b9473f2b..136eb16888 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_photoshop.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_photoshop.json @@ -2,7 +2,7 @@ "type": "dict", "key": "photoshop", "label": "Adobe Photoshop", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_resolve.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_resolve.json index c7aa4e15d3..2d11e1def4 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_resolve.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_resolve.json @@ -2,7 +2,7 @@ "type": "dict", "key": "resolve", "label": "Blackmagic DaVinci Resolve", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_shell.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_shell.json index f1241ea3bd..4fdbd65c24 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_shell.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_shell.json @@ -2,7 +2,7 @@ "type": "dict", "key": "shell", "label": "Shell", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_tvpaint.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_tvpaint.json index b328e5cf79..1c88d12cab 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_tvpaint.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_tvpaint.json @@ -2,7 +2,7 @@ "type": "dict", "key": "tvpaint", "label": "TVPaint", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/schema_unreal.json b/pype/settings/entities/schemas/system_schema/host_settings/schema_unreal.json index 8560d8782e..d7065ad3ff 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/schema_unreal.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/schema_unreal.json @@ -2,7 +2,7 @@ "type": "dict", "key": "unreal", "label": "Unreal Editor", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/template_host_variant.json b/pype/settings/entities/schemas/system_schema/host_settings/template_host_variant.json index cea7da3a81..06f7859117 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/template_host_variant.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/template_host_variant.json @@ -9,7 +9,7 @@ "type": "dict", "key": "{host_name}_{host_version}", "label": "{host_version}", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/host_settings/template_nuke.json b/pype/settings/entities/schemas/system_schema/host_settings/template_nuke.json index a1f975c2a7..01c3be726a 100644 --- a/pype/settings/entities/schemas/system_schema/host_settings/template_nuke.json +++ b/pype/settings/entities/schemas/system_schema/host_settings/template_nuke.json @@ -3,7 +3,7 @@ "type": "dict", "key": "{nuke_type}", "label": "Foundry {nuke_label}", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json b/pype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json index 0683bd10b5..5647e14ebf 100644 --- a/pype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json +++ b/pype/settings/entities/schemas/system_schema/module_settings/schema_ftrack.json @@ -2,7 +2,7 @@ "type": "dict", "key": "ftrack", "label": "Ftrack", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { @@ -58,7 +58,7 @@ "key": "intent", "type": "dict", "label": "Intent", - "collapsable_key": true, + "collapsible_key": true, "is_group": true, "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/schema_applications.json b/pype/settings/entities/schemas/system_schema/schema_applications.json index e2b882ba7d..61d47df8b6 100644 --- a/pype/settings/entities/schemas/system_schema/schema_applications.json +++ b/pype/settings/entities/schemas/system_schema/schema_applications.json @@ -2,7 +2,7 @@ "key": "applications", "type": "dict", "label": "Applications", - "collapsable": true, + "collapsible": true, "is_file": true, "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/schema_general.json b/pype/settings/entities/schemas/system_schema/schema_general.json index a919526de8..f75b584c1b 100644 --- a/pype/settings/entities/schemas/system_schema/schema_general.json +++ b/pype/settings/entities/schemas/system_schema/schema_general.json @@ -2,7 +2,7 @@ "key": "general", "type": "dict", "label": "General", - "collapsable": true, + "collapsible": true, "is_file": true, "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/schema_modules.json b/pype/settings/entities/schemas/system_schema/schema_modules.json index a3b34a37c7..7c45cebabb 100644 --- a/pype/settings/entities/schemas/system_schema/schema_modules.json +++ b/pype/settings/entities/schemas/system_schema/schema_modules.json @@ -2,14 +2,14 @@ "key": "modules", "type": "dict", "label": "Modules", - "collapsable": true, + "collapsible": true, "is_file": true, "children": [ { "type": "dict", "key": "avalon", "label": "Avalon", - "collapsable": true, + "collapsible": true, "children": [ { "type": "text", @@ -45,7 +45,7 @@ "type": "dict", "key": "rest_api", "label": "Rest Api", - "collapsable": true, + "collapsible": true, "children": [ { "type": "number", @@ -70,7 +70,7 @@ "type": "dict", "key": "timers_manager", "label": "Timers Manager", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { @@ -96,7 +96,7 @@ "type": "dict", "key": "clockify", "label": "Clockify", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { @@ -114,7 +114,7 @@ "type": "dict", "key": "sync_server", "label": "Sync Server", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [{ "type": "boolean", @@ -125,7 +125,7 @@ "type": "dict", "key": "deadline", "label": "Deadline", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { @@ -144,7 +144,7 @@ "type": "dict", "key": "muster", "label": "Muster", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { @@ -175,7 +175,7 @@ "type": "dict", "key": "log_viewer", "label": "Logging", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { @@ -189,7 +189,7 @@ "type": "dict", "key": "user", "label": "User setting", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { @@ -203,7 +203,7 @@ "type": "dict", "key": "standalonepublish_tool", "label": "Standalone Publish", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { @@ -217,7 +217,7 @@ "type": "dict", "key": "idle_manager", "label": "Idle Manager", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/schema_tools.json b/pype/settings/entities/schemas/system_schema/schema_tools.json index c8f4829a09..2c04abc47c 100644 --- a/pype/settings/entities/schemas/system_schema/schema_tools.json +++ b/pype/settings/entities/schemas/system_schema/schema_tools.json @@ -2,7 +2,7 @@ "key": "tools", "type": "dict", "label": "Tools", - "collapsable": true, + "collapsible": true, "is_file": true, "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/tool_settings/schema_arnold.json b/pype/settings/entities/schemas/system_schema/tool_settings/schema_arnold.json index aa50610ddc..db2be09c83 100644 --- a/pype/settings/entities/schemas/system_schema/tool_settings/schema_arnold.json +++ b/pype/settings/entities/schemas/system_schema/tool_settings/schema_arnold.json @@ -2,7 +2,7 @@ "type": "dict", "key": "mtoa", "label": "Autodesk Arnold", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/tool_settings/schema_vray.json b/pype/settings/entities/schemas/system_schema/tool_settings/schema_vray.json index 0ce24a310c..fdb25610e0 100644 --- a/pype/settings/entities/schemas/system_schema/tool_settings/schema_vray.json +++ b/pype/settings/entities/schemas/system_schema/tool_settings/schema_vray.json @@ -2,7 +2,7 @@ "type": "dict", "key": "vray", "label": "Chaos Group Vray", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/settings/entities/schemas/system_schema/tool_settings/schema_yeti.json b/pype/settings/entities/schemas/system_schema/tool_settings/schema_yeti.json index b94dbbfcaa..96c6b624fc 100644 --- a/pype/settings/entities/schemas/system_schema/tool_settings/schema_yeti.json +++ b/pype/settings/entities/schemas/system_schema/tool_settings/schema_yeti.json @@ -2,7 +2,7 @@ "type": "dict", "key": "yeti", "label": "Pergrine Labs Yeti", - "collapsable": true, + "collapsible": true, "checkbox_key": "enabled", "children": [ { diff --git a/pype/tools/settings/settings/README.md b/pype/tools/settings/settings/README.md index 643043b6c8..65d73a0728 100644 --- a/pype/tools/settings/settings/README.md +++ b/pype/tools/settings/settings/README.md @@ -126,8 +126,8 @@ - without label it is just wrap item holding `"key"` - can't have `"is_group"` key set to True as it breaks visual override showing - if `"label"` is entetered there which will be shown in GUI - - item with label can be collapsable - - that can be set with key `"collapsable"` as `True`/`False` (Default: `True`) + - item with label can be collapsible + - that can be set with key `"collapsible"` as `True`/`False` (Default: `True`) - with key `"collapsed"` as `True`/`False` can be set that is collapsed when GUI is opened (Default: `False`) - it is possible to add darker background with `"highlight_content"` (Default: `False`) - darker background has limits of maximum applies after 3-4 nested highlighted items there is not difference in the color @@ -138,7 +138,7 @@ "key": "applications", "type": "dict", "label": "Applications", - "collapsable": true, + "collapsible": true, "highlight_content": true, "is_group": true, "is_file": true, @@ -320,8 +320,8 @@ - there are 2 possible ways how to set the type: 1.) dictionary with item modifiers (`number` input has `minimum`, `maximum` and `decimals`) in that case item type must be set as value of `"type"` (example below) 2.) item type name as string without modifiers (e.g. `text`) -- this input can be collapsable - - that can be set with key `"collapsable"` as `True`/`False` (Default: `True`) +- this input can be collapsible + - that can be set with key `"collapsible"` as `True`/`False` (Default: `True`) - with key `"collapsed"` as `True`/`False` can be set that is collapsed when GUI is opened (Default: `False`) 1.) with item modifiers diff --git a/pype/tools/settings/settings/widgets/wrapper_widgets.py b/pype/tools/settings/settings/widgets/wrapper_widgets.py index 790fb81d87..9d5fdeb213 100644 --- a/pype/tools/settings/settings/widgets/wrapper_widgets.py +++ b/pype/tools/settings/settings/widgets/wrapper_widgets.py @@ -56,7 +56,7 @@ class FormWrapper(WrapperWidget): class CollapsibleWrapper(WrapperWidget): def create_ui(self): - self.collapsible = self.schema_data.get("collapsable", True) + self.collapsible = self.schema_data.get("collapsible", True) self.collapsed = self.schema_data.get("collapsed", True) content_widget = QtWidgets.QWidget(self) From 79fcbfdd4bc81e16622be77d9ead8435a6cf17bd Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 18 Feb 2021 10:24:18 +0100 Subject: [PATCH 81/83] simplified `trigger_hierarchical_style_update` --- pype/tools/settings/settings/widgets/base.py | 6 +++--- pype/tools/settings/settings/widgets/categories.py | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pype/tools/settings/settings/widgets/base.py b/pype/tools/settings/settings/widgets/base.py index 3a80bb936b..692e9a9859 100644 --- a/pype/tools/settings/settings/widgets/base.py +++ b/pype/tools/settings/settings/widgets/base.py @@ -9,9 +9,6 @@ class BaseWidget(QtWidgets.QWidget): self.entity = entity self.entity_widget = entity_widget - self.trigger_hierarchical_style_update = ( - self.entity_widget.trigger_hierarchical_style_update - ) self.ignore_input_changes = entity_widget.ignore_input_changes self._is_invalid = False @@ -24,6 +21,9 @@ class BaseWidget(QtWidgets.QWidget): self.label_widget = None self.create_ui() + def trigger_hierarchical_style_update(self): + self.category_widget.hierarchical_style_update() + def create_ui_for_entity(self, *args, **kwargs): return self.category_widget.create_ui_for_entity(*args, **kwargs) diff --git a/pype/tools/settings/settings/widgets/categories.py b/pype/tools/settings/settings/widgets/categories.py index a471775a57..40bd687faf 100644 --- a/pype/tools/settings/settings/widgets/categories.py +++ b/pype/tools/settings/settings/widgets/categories.py @@ -245,9 +245,6 @@ class SettingsCategoryWidget(QtWidgets.QWidget): for input_field in self.input_fields: input_field.hierarchical_style_update() - def trigger_hierarchical_style_update(self): - self.hierarchical_style_update() - def _on_entity_change(self): self.hierarchical_style_update() From e3da1d336628d982d498bc6f1725b402c67a37c4 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 18 Feb 2021 10:35:09 +0100 Subject: [PATCH 82/83] remov one todo --- pype/settings/entities/root_entities.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pype/settings/entities/root_entities.py b/pype/settings/entities/root_entities.py index 32696e7458..53cfbb5f3d 100644 --- a/pype/settings/entities/root_entities.py +++ b/pype/settings/entities/root_entities.py @@ -36,9 +36,6 @@ from pype.settings.lib import ( find_environments, apply_overrides ) -# TODO implement -# ProjectSettings -# AnatomySettings class RootEntity(BaseItemEntity): From 4fd76a07129cca0d8e8244a13ede1641d6043324 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 18 Feb 2021 16:47:01 +0100 Subject: [PATCH 83/83] add ProjectSettings to pype.api --- pype/api.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pype/api.py b/pype/api.py index d7003bffa7..63bab71da1 100644 --- a/pype/api.py +++ b/pype/api.py @@ -5,7 +5,8 @@ from .settings import ( get_anatomy_settings, get_environments, - SystemSettings + SystemSettings, + ProjectSettings ) from .lib import ( PypeLogger,