From e2076c0f2fa264f4dc7ae6959c3292b60616ca91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20David?= Date: Thu, 3 Feb 2022 19:03:16 +0100 Subject: [PATCH] Module: Kitsu module --- .../modules/default_modules/kitsu/__init__.py | 15 ++ .../default_modules/kitsu/kitsu_module.py | 147 ++++++++++++++++++ .../kitsu/plugins/publish/example_plugin.py | 9 ++ .../schemas/project_schemas/main.json | 30 ++++ .../schemas/project_schemas/the_template.json | 30 ++++ .../modules/default_modules/kitsu/widgets.py | 31 ++++ .../defaults/project_settings/kitsu.json | 3 + .../defaults/system_settings/modules.json | 4 + .../schemas/projects_schema/schema_main.json | 4 + .../projects_schema/schema_project_kitsu.json | 17 ++ .../module_settings/schema_kitsu.json | 23 +++ .../schemas/system_schema/schema_modules.json | 4 + 12 files changed, 317 insertions(+) create mode 100644 openpype/modules/default_modules/kitsu/__init__.py create mode 100644 openpype/modules/default_modules/kitsu/kitsu_module.py create mode 100644 openpype/modules/default_modules/kitsu/plugins/publish/example_plugin.py create mode 100644 openpype/modules/default_modules/kitsu/settings/schemas/project_schemas/main.json create mode 100644 openpype/modules/default_modules/kitsu/settings/schemas/project_schemas/the_template.json create mode 100644 openpype/modules/default_modules/kitsu/widgets.py create mode 100644 openpype/settings/defaults/project_settings/kitsu.json create mode 100644 openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json create mode 100644 openpype/settings/entities/schemas/system_schema/module_settings/schema_kitsu.json diff --git a/openpype/modules/default_modules/kitsu/__init__.py b/openpype/modules/default_modules/kitsu/__init__.py new file mode 100644 index 0000000000..cd0c2ea8af --- /dev/null +++ b/openpype/modules/default_modules/kitsu/__init__.py @@ -0,0 +1,15 @@ +""" Addon class definition and Settings definition must be imported here. + +If addon class or settings definition won't be here their definition won't +be found by OpenPype discovery. +""" + +from .kitsu_module import ( + AddonSettingsDef, + KitsuModule +) + +__all__ = ( + "AddonSettingsDef", + "KitsuModule" +) diff --git a/openpype/modules/default_modules/kitsu/kitsu_module.py b/openpype/modules/default_modules/kitsu/kitsu_module.py new file mode 100644 index 0000000000..81d7e56a81 --- /dev/null +++ b/openpype/modules/default_modules/kitsu/kitsu_module.py @@ -0,0 +1,147 @@ +"""Addon definition is located here. + +Import of python packages that may not be available should not be imported +in global space here until are required or used. +- Qt related imports +- imports of Python 3 packages + - we still support Python 2 hosts where addon definition should available +""" + +import os +import click + +from openpype.modules import ( + JsonFilesSettingsDef, + OpenPypeModule, + ModulesManager +) +# Import interface defined by this addon to be able find other addons using it +from openpype_interfaces import ( + IPluginPaths, + ITrayAction +) + + +# Settings definition of this addon using `JsonFilesSettingsDef` +# - JsonFilesSettingsDef is prepared settings definition using json files +# to define settings and store default values +class AddonSettingsDef(JsonFilesSettingsDef): + # This will add prefixes to every schema and template from `schemas` + # subfolder. + # - it is not required to fill the prefix but it is highly + # recommended as schemas and templates may have name clashes across + # multiple addons + # - it is also recommended that prefix has addon name in it + schema_prefix = "kitsu" + + def get_settings_root_path(self): + """Implemented abstract class of JsonFilesSettingsDef. + + Return directory path where json files defying addon settings are + located. + """ + return os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "settings" + ) + + +class KitsuModule(OpenPypeModule, IPluginPaths, ITrayAction): + """This Addon has defined it's settings and interface. + + This example has system settings with an enabled option. And use + few other interfaces: + - `IPluginPaths` to define custom plugin paths + - `ITrayAction` to be shown in tray tool + """ + label = "Kitsu" + name = "kitsu" + + def initialize(self, settings): + """Initialization of addon.""" + module_settings = settings[self.name] + # Enabled by settings + self.enabled = module_settings.get("enabled", False) + + # Prepare variables that can be used or set afterwards + self._connected_modules = None + # UI which must not be created at this time + self._dialog = None + + def tray_init(self): + """Implementation of abstract method for `ITrayAction`. + + We're definitely in tray tool so we can pre create dialog. + """ + + self._create_dialog() + + def _create_dialog(self): + # Don't recreate dialog if already exists + if self._dialog is not None: + return + + from .widgets import MyExampleDialog + + self._dialog = MyExampleDialog() + + def show_dialog(self): + """Show dialog with connected modules. + + This can be called from anywhere but can also crash in headless mode. + There is no way to prevent addon to do invalid operations if he's + not handling them. + """ + # Make sure dialog is created + self._create_dialog() + # Show dialog + self._dialog.open() + + def get_connected_modules(self): + """Custom implementation of addon.""" + names = set() + if self._connected_modules is not None: + for module in self._connected_modules: + names.add(module.name) + return names + + def on_action_trigger(self): + """Implementation of abstract method for `ITrayAction`.""" + self.show_dialog() + + def get_plugin_paths(self): + """Implementation of abstract method for `IPluginPaths`.""" + current_dir = os.path.dirname(os.path.abspath(__file__)) + + return { + "publish": [os.path.join(current_dir, "plugins", "publish")] + } + + def cli(self, click_group): + click_group.add_command(cli_main) + + +@click.group(KitsuModule.name, help="Kitsu dynamic cli commands.") +def cli_main(): + pass + + +@cli_main.command() +def nothing(): + """Does nothing but print a message.""" + print("You've triggered \"nothing\" command.") + + +@cli_main.command() +def show_dialog(): + """Show ExampleAddon dialog. + + We don't have access to addon directly through cli so we have to create + it again. + """ + from openpype.tools.utils.lib import qt_app_context + + manager = ModulesManager() + example_addon = manager.modules_by_name[KitsuModule.name] + with qt_app_context(): + example_addon.show_dialog() diff --git a/openpype/modules/default_modules/kitsu/plugins/publish/example_plugin.py b/openpype/modules/default_modules/kitsu/plugins/publish/example_plugin.py new file mode 100644 index 0000000000..61602f4e78 --- /dev/null +++ b/openpype/modules/default_modules/kitsu/plugins/publish/example_plugin.py @@ -0,0 +1,9 @@ +import pyblish.api + + +class CollectExampleAddon(pyblish.api.ContextPlugin): + order = pyblish.api.CollectorOrder + 0.4 + label = "Collect Kitsu" + + def process(self, context): + self.log.info("I'm in Kitsu's plugin!") diff --git a/openpype/modules/default_modules/kitsu/settings/schemas/project_schemas/main.json b/openpype/modules/default_modules/kitsu/settings/schemas/project_schemas/main.json new file mode 100644 index 0000000000..82e58ce9ab --- /dev/null +++ b/openpype/modules/default_modules/kitsu/settings/schemas/project_schemas/main.json @@ -0,0 +1,30 @@ +{ + "type": "dict", + "key": "kitsu", + "label": " Kitsu", + "collapsible": true, + "children": [ + { + "type": "number", + "key": "number", + "label": "This is your lucky number:", + "minimum": 7, + "maximum": 7, + "decimals": 0 + }, + { + "type": "template", + "name": "kitsu/the_template", + "template_data": [ + { + "name": "color_1", + "label": "Color 1" + }, + { + "name": "color_2", + "label": "Color 2" + } + ] + } + ] +} diff --git a/openpype/modules/default_modules/kitsu/settings/schemas/project_schemas/the_template.json b/openpype/modules/default_modules/kitsu/settings/schemas/project_schemas/the_template.json new file mode 100644 index 0000000000..af8fd9dae4 --- /dev/null +++ b/openpype/modules/default_modules/kitsu/settings/schemas/project_schemas/the_template.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 + } + ] + } +] diff --git a/openpype/modules/default_modules/kitsu/widgets.py b/openpype/modules/default_modules/kitsu/widgets.py new file mode 100644 index 0000000000..de232113fe --- /dev/null +++ b/openpype/modules/default_modules/kitsu/widgets.py @@ -0,0 +1,31 @@ +from Qt import QtWidgets + +from openpype.style import load_stylesheet + + +class MyExampleDialog(QtWidgets.QDialog): + def __init__(self, parent=None): + super(MyExampleDialog, self).__init__(parent) + + self.setWindowTitle("Connected modules") + + msg = "This is example dialog of Kitsu." + label_widget = QtWidgets.QLabel(msg, self) + + ok_btn = QtWidgets.QPushButton("OK", self) + btns_layout = QtWidgets.QHBoxLayout() + btns_layout.addStretch(1) + btns_layout.addWidget(ok_btn) + + layout = QtWidgets.QVBoxLayout(self) + layout.addWidget(label_widget) + layout.addLayout(btns_layout) + + ok_btn.clicked.connect(self._on_ok_clicked) + + self._label_widget = label_widget + + self.setStyleSheet(load_stylesheet()) + + def _on_ok_clicked(self): + self.done(1) diff --git a/openpype/settings/defaults/project_settings/kitsu.json b/openpype/settings/defaults/project_settings/kitsu.json new file mode 100644 index 0000000000..b4d2ccc611 --- /dev/null +++ b/openpype/settings/defaults/project_settings/kitsu.json @@ -0,0 +1,3 @@ +{ + "number": 0 +} \ No newline at end of file diff --git a/openpype/settings/defaults/system_settings/modules.json b/openpype/settings/defaults/system_settings/modules.json index d74269922f..9cfaddecbe 100644 --- a/openpype/settings/defaults/system_settings/modules.json +++ b/openpype/settings/defaults/system_settings/modules.json @@ -137,6 +137,10 @@ } } }, + "kitsu": { + "enabled": false, + "kitsu_server": "" + }, "timers_manager": { "enabled": true, "auto_stop": true, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_main.json b/openpype/settings/entities/schemas/projects_schema/schema_main.json index dbddd18c80..6c07209de3 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_main.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_main.json @@ -62,6 +62,10 @@ "type": "schema", "name": "schema_project_ftrack" }, + { + "type": "schema", + "name": "schema_project_kitsu" + }, { "type": "schema", "name": "schema_project_deadline" diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json new file mode 100644 index 0000000000..93976cc03b --- /dev/null +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_kitsu.json @@ -0,0 +1,17 @@ +{ + "type": "dict", + "key": "kitsu", + "label": "Kitsu", + "collapsible": true, + "is_file": true, + "children": [ + { + "type": "number", + "key": "number", + "label": "This is your lucky number:", + "minimum": 7, + "maximum": 7, + "decimals": 0 + } + ] +} diff --git a/openpype/settings/entities/schemas/system_schema/module_settings/schema_kitsu.json b/openpype/settings/entities/schemas/system_schema/module_settings/schema_kitsu.json new file mode 100644 index 0000000000..8e496dc783 --- /dev/null +++ b/openpype/settings/entities/schemas/system_schema/module_settings/schema_kitsu.json @@ -0,0 +1,23 @@ +{ + "type": "dict", + "key": "kitsu", + "label": "Kitsu", + "collapsible": true, + "require_restart": true, + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "text", + "key": "kitsu_server", + "label": "Server" + }, + { + "type": "splitter" + } + ] +} diff --git a/openpype/settings/entities/schemas/system_schema/schema_modules.json b/openpype/settings/entities/schemas/system_schema/schema_modules.json index 52595914ed..d22b9016a7 100644 --- a/openpype/settings/entities/schemas/system_schema/schema_modules.json +++ b/openpype/settings/entities/schemas/system_schema/schema_modules.json @@ -44,6 +44,10 @@ "type": "schema", "name": "schema_ftrack" }, + { + "type": "schema", + "name": "schema_kitsu" + }, { "type": "dict", "key": "timers_manager",