Skip to content

interfaces

Addon interfaces for AYON.

AYONInterface

Base class of Interface that can be used as Mixin with abstract parts.

This is way how AYON addon can define that contains specific predefined functionality.

Child classes of AYONInterface may be used as mixin in different AYON addons which means they have to have implemented methods defined in the interface. By default, interface does not have any abstract parts.

Source code in client/ayon_core/addon/interfaces.py
28
29
30
31
32
33
34
35
36
37
38
39
class AYONInterface(metaclass=_AYONInterfaceMeta):
    """Base class of Interface that can be used as Mixin with abstract parts.

    This is way how AYON addon can define that contains specific predefined
    functionality.

    Child classes of AYONInterface may be used as mixin in different
    AYON addons which means they have to have implemented methods defined
    in the interface. By default, interface does not have any abstract parts.
    """

    log = None

IHostAddon

Bases: AYONInterface

Addon which also contain a host implementation.

Source code in client/ayon_core/addon/interfaces.py
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
class IHostAddon(AYONInterface):
    """Addon which also contain a host implementation."""

    @property
    @abstractmethod
    def host_name(self) -> str:
        """Name of host which addon represents."""

    def get_workfile_extensions(self) -> list[str]:  # noqa: PLR6301
        """Define workfile extensions for host.

        Not all hosts support workfiles thus this is optional implementation.

        Returns:
            List[str]: Extensions used for workfiles with dot.

        """
        return []

host_name abstractmethod property

Name of host which addon represents.

get_workfile_extensions()

Define workfile extensions for host.

Not all hosts support workfiles thus this is optional implementation.

Returns:

Type Description
list[str]

List[str]: Extensions used for workfiles with dot.

Source code in client/ayon_core/addon/interfaces.py
494
495
496
497
498
499
500
501
502
503
def get_workfile_extensions(self) -> list[str]:  # noqa: PLR6301
    """Define workfile extensions for host.

    Not all hosts support workfiles thus this is optional implementation.

    Returns:
        List[str]: Extensions used for workfiles with dot.

    """
    return []

IPluginPaths

Bases: AYONInterface

Addon wants to register plugin paths.

Source code in client/ayon_core/addon/interfaces.py
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
class IPluginPaths(AYONInterface):
    """Addon wants to register plugin paths."""

    def get_plugin_paths(self) -> dict[str, list[str]]:
        """Return plugin paths for addon.

        This method was abstract (required) in the past, so raise the required
            'core' addon version when 'get_plugin_paths' is removed from
            addon.

        Deprecated:
            Please implement specific methods 'get_create_plugin_paths',
                'get_load_plugin_paths', 'get_inventory_action_paths' and
                'get_publish_plugin_paths' to return plugin paths.

        Returns:
            dict[str, list[str]]: Plugin paths for addon.

        """
        return {}

    def _get_plugin_paths_by_type(
        self, plugin_type: str
    ) -> list[str]:
        """Get plugin paths by type.

        Args:
            plugin_type (str): Type of plugin paths to get.

        Returns:
            list[str]: List of plugin paths.

        """
        paths = self.get_plugin_paths()
        if not paths or plugin_type not in paths:
            return []

        paths = paths[plugin_type]
        if not paths:
            return []

        if not isinstance(paths, (list, tuple, set)):
            paths = [paths]

        new_function_name = "get_launcher_action_paths"
        if plugin_type == "create":
            new_function_name = "get_create_plugin_paths"
        elif plugin_type == "load":
            new_function_name = "get_load_plugin_paths"
        elif plugin_type == "publish":
            new_function_name = "get_publish_plugin_paths"
        elif plugin_type == "inventory":
            new_function_name = "get_inventory_action_paths"

        warnings.warn(
            f"Addon '{self.name}' returns '{plugin_type}' paths using"
            " 'get_plugin_paths' method. Please implement"
            f" '{new_function_name}' instead.",
            DeprecationWarning,
            stacklevel=2
        )
        return paths

    def get_launcher_action_paths(self) -> list[str]:
        """Receive launcher actions paths.

        Give addons ability to add launcher actions paths.

        Returns:
            list[str]: List of launcher action paths.

        """
        return self._get_plugin_paths_by_type("actions")

    def get_create_plugin_paths(self, host_name: str) -> list[str]:
        """Receive create plugin paths.

        Give addons ability to add create plugin paths based on host name.

        Notes:
            Default implementation uses 'get_plugin_paths' and always return
                all create plugin paths.

        Args:
            host_name (str): For which host are the plugins meant.

        Returns:
            list[str]: List of create plugin paths.

        """
        return self._get_plugin_paths_by_type("create")

    def get_load_plugin_paths(self, host_name: str) -> list[str]:
        """Receive load plugin paths.

        Give addons ability to add load plugin paths based on host name.

        Notes:
            Default implementation uses 'get_plugin_paths' and always return
                all load plugin paths.

        Args:
            host_name (str): For which host are the plugins meant.

        Returns:
            list[str]: List of load plugin paths.

        """
        return self._get_plugin_paths_by_type("load")

    def get_publish_plugin_paths(self, host_name: str) -> list[str]:
        """Receive publish plugin paths.

        Give addons ability to add publish plugin paths based on host name.

        Notes:
           Default implementation uses 'get_plugin_paths' and always return
               all publish plugin paths.

        Args:
           host_name (str): For which host are the plugins meant.

        Returns:
            list[str]: List of publish plugin paths.

        """
        return self._get_plugin_paths_by_type("publish")

    def get_inventory_action_paths(self, host_name: str) -> list[str]:
        """Receive inventory action paths.

        Give addons ability to add inventory action plugin paths.

        Notes:
           Default implementation uses 'get_plugin_paths' and always return
               all publish plugin paths.

        Args:
           host_name (str): For which host are the plugins meant.

        Returns:
            list[str]: List of inventory action plugin paths.

        """
        return self._get_plugin_paths_by_type("inventory")

get_create_plugin_paths(host_name)

Receive create plugin paths.

Give addons ability to add create plugin paths based on host name.

Notes

Default implementation uses 'get_plugin_paths' and always return all create plugin paths.

Parameters:

Name Type Description Default
host_name str

For which host are the plugins meant.

required

Returns:

Type Description
list[str]

list[str]: List of create plugin paths.

Source code in client/ayon_core/addon/interfaces.py
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
def get_create_plugin_paths(self, host_name: str) -> list[str]:
    """Receive create plugin paths.

    Give addons ability to add create plugin paths based on host name.

    Notes:
        Default implementation uses 'get_plugin_paths' and always return
            all create plugin paths.

    Args:
        host_name (str): For which host are the plugins meant.

    Returns:
        list[str]: List of create plugin paths.

    """
    return self._get_plugin_paths_by_type("create")

get_inventory_action_paths(host_name)

Receive inventory action paths.

Give addons ability to add inventory action plugin paths.

Notes

Default implementation uses 'get_plugin_paths' and always return all publish plugin paths.

Parameters:

Name Type Description Default
host_name str

For which host are the plugins meant.

required

Returns:

Type Description
list[str]

list[str]: List of inventory action plugin paths.

Source code in client/ayon_core/addon/interfaces.py
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
def get_inventory_action_paths(self, host_name: str) -> list[str]:
    """Receive inventory action paths.

    Give addons ability to add inventory action plugin paths.

    Notes:
       Default implementation uses 'get_plugin_paths' and always return
           all publish plugin paths.

    Args:
       host_name (str): For which host are the plugins meant.

    Returns:
        list[str]: List of inventory action plugin paths.

    """
    return self._get_plugin_paths_by_type("inventory")

get_launcher_action_paths()

Receive launcher actions paths.

Give addons ability to add launcher actions paths.

Returns:

Type Description
list[str]

list[str]: List of launcher action paths.

Source code in client/ayon_core/addon/interfaces.py
105
106
107
108
109
110
111
112
113
114
def get_launcher_action_paths(self) -> list[str]:
    """Receive launcher actions paths.

    Give addons ability to add launcher actions paths.

    Returns:
        list[str]: List of launcher action paths.

    """
    return self._get_plugin_paths_by_type("actions")

get_load_plugin_paths(host_name)

Receive load plugin paths.

Give addons ability to add load plugin paths based on host name.

Notes

Default implementation uses 'get_plugin_paths' and always return all load plugin paths.

Parameters:

Name Type Description Default
host_name str

For which host are the plugins meant.

required

Returns:

Type Description
list[str]

list[str]: List of load plugin paths.

Source code in client/ayon_core/addon/interfaces.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
def get_load_plugin_paths(self, host_name: str) -> list[str]:
    """Receive load plugin paths.

    Give addons ability to add load plugin paths based on host name.

    Notes:
        Default implementation uses 'get_plugin_paths' and always return
            all load plugin paths.

    Args:
        host_name (str): For which host are the plugins meant.

    Returns:
        list[str]: List of load plugin paths.

    """
    return self._get_plugin_paths_by_type("load")

get_plugin_paths()

Return plugin paths for addon.

This method was abstract (required) in the past, so raise the required 'core' addon version when 'get_plugin_paths' is removed from addon.

Deprecated

Please implement specific methods 'get_create_plugin_paths', 'get_load_plugin_paths', 'get_inventory_action_paths' and 'get_publish_plugin_paths' to return plugin paths.

Returns:

Type Description
dict[str, list[str]]

dict[str, list[str]]: Plugin paths for addon.

Source code in client/ayon_core/addon/interfaces.py
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
def get_plugin_paths(self) -> dict[str, list[str]]:
    """Return plugin paths for addon.

    This method was abstract (required) in the past, so raise the required
        'core' addon version when 'get_plugin_paths' is removed from
        addon.

    Deprecated:
        Please implement specific methods 'get_create_plugin_paths',
            'get_load_plugin_paths', 'get_inventory_action_paths' and
            'get_publish_plugin_paths' to return plugin paths.

    Returns:
        dict[str, list[str]]: Plugin paths for addon.

    """
    return {}

get_publish_plugin_paths(host_name)

Receive publish plugin paths.

Give addons ability to add publish plugin paths based on host name.

Notes

Default implementation uses 'get_plugin_paths' and always return all publish plugin paths.

Parameters:

Name Type Description Default
host_name str

For which host are the plugins meant.

required

Returns:

Type Description
list[str]

list[str]: List of publish plugin paths.

Source code in client/ayon_core/addon/interfaces.py
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
def get_publish_plugin_paths(self, host_name: str) -> list[str]:
    """Receive publish plugin paths.

    Give addons ability to add publish plugin paths based on host name.

    Notes:
       Default implementation uses 'get_plugin_paths' and always return
           all publish plugin paths.

    Args:
       host_name (str): For which host are the plugins meant.

    Returns:
        list[str]: List of publish plugin paths.

    """
    return self._get_plugin_paths_by_type("publish")

ITraits

Bases: AYONInterface

Interface for traits.

Source code in client/ayon_core/addon/interfaces.py
506
507
508
509
510
511
512
513
514
515
516
class ITraits(AYONInterface):
    """Interface for traits."""

    @abstractmethod
    def get_addon_traits(self) -> list[Type[TraitBase]]:
        """Get trait classes for the addon.

        Returns:
            list[Type[TraitBase]]: Traits for the addon.

        """

get_addon_traits() abstractmethod

Get trait classes for the addon.

Returns:

Type Description
list[Type[TraitBase]]

list[Type[TraitBase]]: Traits for the addon.

Source code in client/ayon_core/addon/interfaces.py
509
510
511
512
513
514
515
516
@abstractmethod
def get_addon_traits(self) -> list[Type[TraitBase]]:
    """Get trait classes for the addon.

    Returns:
        list[Type[TraitBase]]: Traits for the addon.

    """

ITrayAction

Bases: ITrayAddon

Implementation of Tray action.

Add action to tray menu which will trigger on_action_trigger. It is expected to be used for showing tools.

Methods tray_start, tray_exit and connect_with_addons are overridden as it's not expected that action will use them. But it is possible if necessary.

Source code in client/ayon_core/addon/interfaces.py
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
class ITrayAction(ITrayAddon):
    """Implementation of Tray action.

    Add action to tray menu which will trigger `on_action_trigger`.
    It is expected to be used for showing tools.

    Methods `tray_start`, `tray_exit` and `connect_with_addons` are overridden
    as it's not expected that action will use them. But it is possible if
    necessary.
    """

    admin_action = False
    _action_item = None

    @property
    @abstractmethod
    def label(self) -> str:
        """Service label showed in menu."""

    @abstractmethod
    def on_action_trigger(self) -> None:
        """What happens on actions click."""

    def tray_menu(self, tray_menu: QtWidgets.QMenu) -> None:
        """Add action to tray menu."""
        from qtpy import QtWidgets

        if self.admin_action:
            action = self.add_action_to_admin_submenu(self.label, tray_menu)
        else:
            action = QtWidgets.QAction(self.label, tray_menu)
            tray_menu.addAction(action)

        action.triggered.connect(self.on_action_trigger)
        self._action_item = action

    def tray_start(self) -> None:  # noqa: PLR6301
        """Start procedure in tray tool."""
        return

    def tray_exit(self) -> None:  # noqa: PLR6301
        """Cleanup method which is executed on tray shutdown."""
        return

label abstractmethod property

Service label showed in menu.

on_action_trigger() abstractmethod

What happens on actions click.

Source code in client/ayon_core/addon/interfaces.py
335
336
337
@abstractmethod
def on_action_trigger(self) -> None:
    """What happens on actions click."""

tray_exit()

Cleanup method which is executed on tray shutdown.

Source code in client/ayon_core/addon/interfaces.py
356
357
358
def tray_exit(self) -> None:  # noqa: PLR6301
    """Cleanup method which is executed on tray shutdown."""
    return

tray_menu(tray_menu)

Add action to tray menu.

Source code in client/ayon_core/addon/interfaces.py
339
340
341
342
343
344
345
346
347
348
349
350
def tray_menu(self, tray_menu: QtWidgets.QMenu) -> None:
    """Add action to tray menu."""
    from qtpy import QtWidgets

    if self.admin_action:
        action = self.add_action_to_admin_submenu(self.label, tray_menu)
    else:
        action = QtWidgets.QAction(self.label, tray_menu)
        tray_menu.addAction(action)

    action.triggered.connect(self.on_action_trigger)
    self._action_item = action

tray_start()

Start procedure in tray tool.

Source code in client/ayon_core/addon/interfaces.py
352
353
354
def tray_start(self) -> None:  # noqa: PLR6301
    """Start procedure in tray tool."""
    return

ITrayAddon

Bases: AYONInterface

Addon has special procedures when used in Tray tool.

Important

The addon. still must be usable if is not used in tray even if it would do nothing.

Source code in client/ayon_core/addon/interfaces.py
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
class ITrayAddon(AYONInterface):
    """Addon has special procedures when used in Tray tool.

    Important:
        The addon. still must be usable if is not used in tray even if it
        would do nothing.

    """
    manager: AddonsManager
    tray_initialized = False
    _tray_manager: TrayManager = None
    _admin_submenu = None

    @abstractmethod
    def tray_init(self) -> None:
        """Initialization part of tray implementation.

        Triggered between `initialization` and `connect_with_addons`.

        This is where GUIs should be loaded or tray specific parts should be
        prepared

        """

    @abstractmethod
    def tray_menu(self, tray_menu: QtWidgets.QMenu) -> None:
        """Add addon's action to tray menu."""

    @abstractmethod
    def tray_start(self) -> None:
        """Start procedure in tray tool."""

    @abstractmethod
    def tray_exit(self) -> None:
        """Cleanup method which is executed on tray shutdown.

        This is place where all threads should be shut.

        """

    def execute_in_main_thread(self, callback: Callable) -> None:
        """Pushes callback to the queue or process 'callback' on a main thread.

        Some callbacks need to be processed on main thread (menu actions
        must be added on main thread else they won't get triggered etc.)

        Args:
            callback (Callable): Function to be executed on main thread

        """
        if not self.tray_initialized:
            # TODO (Illicit): Called without initialized tray, still
            #   main thread needed.
            try:
                callback()

            except Exception:  # noqa: BLE001
                self.log.warning(
                    "Failed to execute %s callback in main thread",
                    str(callback), exc_info=True)

            return
        self._tray_manager.tray_manager.execute_in_main_thread(callback)

    def show_tray_message(
            self,
            title: str,
            message: str,
            icon: Optional[QtWidgets.QSystemTrayIcon] = None,
            msecs: Optional[int] = None) -> None:
        """Show tray message.

        Args:
            title (str): Title of message.
            message (str): Content of message.
            icon (QSystemTrayIcon.MessageIcon): Message's icon. Default is
                Information icon, may differ by Qt version.
            msecs (int): Duration of message visibility in milliseconds.
                Default is 10000 msecs, may differ by Qt version.
        """
        if self._tray_manager:
            self._tray_manager.show_tray_message(title, message, icon, msecs)

    def add_doubleclick_callback(self, callback: Callable) -> None:
        """Add callback to be triggered on tray icon double click."""
        if hasattr(self.manager, "add_doubleclick_callback"):
            self.manager.add_doubleclick_callback(self, callback)

    @staticmethod
    def admin_submenu(tray_menu: QtWidgets.QMenu) -> QtWidgets.QMenu:
        """Get or create admin submenu.

        Returns:
            QtWidgets.QMenu: Admin submenu.

        """
        if ITrayAddon._admin_submenu is None:
            from qtpy import QtWidgets

            admin_submenu = QtWidgets.QMenu("Admin", tray_menu)
            admin_submenu.menuAction().setVisible(False)
            ITrayAddon._admin_submenu = admin_submenu
        return ITrayAddon._admin_submenu

    @staticmethod
    def add_action_to_admin_submenu(
            label: str, tray_menu: QtWidgets.QMenu) -> QtWidgets.QAction:
        """Add action to admin submenu.

        Args:
            label (str): Label of action.
            tray_menu (QtWidgets.QMenu): Tray menu to add action to.

        Returns:
            QtWidgets.QAction: Action added to admin submenu

        """
        from qtpy import QtWidgets

        menu = ITrayAddon.admin_submenu(tray_menu)
        action = QtWidgets.QAction(label, menu)
        menu.addAction(action)
        if not menu.menuAction().isVisible():
            menu.menuAction().setVisible(True)
        return action

add_action_to_admin_submenu(label, tray_menu) staticmethod

Add action to admin submenu.

Parameters:

Name Type Description Default
label str

Label of action.

required
tray_menu QMenu

Tray menu to add action to.

required

Returns:

Type Description
QAction

QtWidgets.QAction: Action added to admin submenu

Source code in client/ayon_core/addon/interfaces.py
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
@staticmethod
def add_action_to_admin_submenu(
        label: str, tray_menu: QtWidgets.QMenu) -> QtWidgets.QAction:
    """Add action to admin submenu.

    Args:
        label (str): Label of action.
        tray_menu (QtWidgets.QMenu): Tray menu to add action to.

    Returns:
        QtWidgets.QAction: Action added to admin submenu

    """
    from qtpy import QtWidgets

    menu = ITrayAddon.admin_submenu(tray_menu)
    action = QtWidgets.QAction(label, menu)
    menu.addAction(action)
    if not menu.menuAction().isVisible():
        menu.menuAction().setVisible(True)
    return action

add_doubleclick_callback(callback)

Add callback to be triggered on tray icon double click.

Source code in client/ayon_core/addon/interfaces.py
272
273
274
275
def add_doubleclick_callback(self, callback: Callable) -> None:
    """Add callback to be triggered on tray icon double click."""
    if hasattr(self.manager, "add_doubleclick_callback"):
        self.manager.add_doubleclick_callback(self, callback)

admin_submenu(tray_menu) staticmethod

Get or create admin submenu.

Returns:

Type Description
QMenu

QtWidgets.QMenu: Admin submenu.

Source code in client/ayon_core/addon/interfaces.py
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
@staticmethod
def admin_submenu(tray_menu: QtWidgets.QMenu) -> QtWidgets.QMenu:
    """Get or create admin submenu.

    Returns:
        QtWidgets.QMenu: Admin submenu.

    """
    if ITrayAddon._admin_submenu is None:
        from qtpy import QtWidgets

        admin_submenu = QtWidgets.QMenu("Admin", tray_menu)
        admin_submenu.menuAction().setVisible(False)
        ITrayAddon._admin_submenu = admin_submenu
    return ITrayAddon._admin_submenu

execute_in_main_thread(callback)

Pushes callback to the queue or process 'callback' on a main thread.

Some callbacks need to be processed on main thread (menu actions must be added on main thread else they won't get triggered etc.)

Parameters:

Name Type Description Default
callback Callable

Function to be executed on main thread

required
Source code in client/ayon_core/addon/interfaces.py
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
def execute_in_main_thread(self, callback: Callable) -> None:
    """Pushes callback to the queue or process 'callback' on a main thread.

    Some callbacks need to be processed on main thread (menu actions
    must be added on main thread else they won't get triggered etc.)

    Args:
        callback (Callable): Function to be executed on main thread

    """
    if not self.tray_initialized:
        # TODO (Illicit): Called without initialized tray, still
        #   main thread needed.
        try:
            callback()

        except Exception:  # noqa: BLE001
            self.log.warning(
                "Failed to execute %s callback in main thread",
                str(callback), exc_info=True)

        return
    self._tray_manager.tray_manager.execute_in_main_thread(callback)

show_tray_message(title, message, icon=None, msecs=None)

Show tray message.

Parameters:

Name Type Description Default
title str

Title of message.

required
message str

Content of message.

required
icon MessageIcon

Message's icon. Default is Information icon, may differ by Qt version.

None
msecs int

Duration of message visibility in milliseconds. Default is 10000 msecs, may differ by Qt version.

None
Source code in client/ayon_core/addon/interfaces.py
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
def show_tray_message(
        self,
        title: str,
        message: str,
        icon: Optional[QtWidgets.QSystemTrayIcon] = None,
        msecs: Optional[int] = None) -> None:
    """Show tray message.

    Args:
        title (str): Title of message.
        message (str): Content of message.
        icon (QSystemTrayIcon.MessageIcon): Message's icon. Default is
            Information icon, may differ by Qt version.
        msecs (int): Duration of message visibility in milliseconds.
            Default is 10000 msecs, may differ by Qt version.
    """
    if self._tray_manager:
        self._tray_manager.show_tray_message(title, message, icon, msecs)

tray_exit() abstractmethod

Cleanup method which is executed on tray shutdown.

This is place where all threads should be shut.

Source code in client/ayon_core/addon/interfaces.py
221
222
223
224
225
226
227
@abstractmethod
def tray_exit(self) -> None:
    """Cleanup method which is executed on tray shutdown.

    This is place where all threads should be shut.

    """

tray_init() abstractmethod

Initialization part of tray implementation.

Triggered between initialization and connect_with_addons.

This is where GUIs should be loaded or tray specific parts should be prepared

Source code in client/ayon_core/addon/interfaces.py
202
203
204
205
206
207
208
209
210
211
@abstractmethod
def tray_init(self) -> None:
    """Initialization part of tray implementation.

    Triggered between `initialization` and `connect_with_addons`.

    This is where GUIs should be loaded or tray specific parts should be
    prepared

    """

tray_menu(tray_menu) abstractmethod

Add addon's action to tray menu.

Source code in client/ayon_core/addon/interfaces.py
213
214
215
@abstractmethod
def tray_menu(self, tray_menu: QtWidgets.QMenu) -> None:
    """Add addon's action to tray menu."""

tray_start() abstractmethod

Start procedure in tray tool.

Source code in client/ayon_core/addon/interfaces.py
217
218
219
@abstractmethod
def tray_start(self) -> None:
    """Start procedure in tray tool."""

ITrayService

Bases: ITrayAddon

Tray service Interface.

Source code in client/ayon_core/addon/interfaces.py
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
class ITrayService(ITrayAddon):
    """Tray service Interface."""
    # Module's property
    menu_action: QtWidgets.QAction = None

    # Class properties
    _services_submenu: QtWidgets.QMenu = None
    _icon_failed: QtWidgets.QIcon = None
    _icon_running: QtWidgets.QIcon = None
    _icon_idle: QtWidgets.QIcon = None

    @property
    @abstractmethod
    def label(self) -> str:
        """Service label showed in menu."""

    # TODO (Illicit): be able to get any sort of information to show/print
    # @abstractmethod
    # def get_service_info(self):
    #     pass

    @staticmethod
    def services_submenu(tray_menu: QtWidgets.QMenu) -> QtWidgets.QMenu:
        """Get or create services submenu.

        Returns:
            QtWidgets.QMenu: Services submenu.

        """
        if ITrayService._services_submenu is None:
            from qtpy import QtWidgets

            services_submenu = QtWidgets.QMenu("Services", tray_menu)
            services_submenu.menuAction().setVisible(False)
            ITrayService._services_submenu = services_submenu
        return ITrayService._services_submenu

    @staticmethod
    def add_service_action(action: QtWidgets.QAction) -> None:
        """Add service action to services submenu."""
        ITrayService._services_submenu.addAction(action)
        if not ITrayService._services_submenu.menuAction().isVisible():
            ITrayService._services_submenu.menuAction().setVisible(True)

    @staticmethod
    def _load_service_icons() -> None:
        """Load service icons."""
        from qtpy import QtGui

        ITrayService._failed_icon = QtGui.QIcon(
            resources.get_resource("icons", "circle_red.png")
        )
        ITrayService._icon_running = QtGui.QIcon(
            resources.get_resource("icons", "circle_green.png")
        )
        ITrayService._icon_idle = QtGui.QIcon(
            resources.get_resource("icons", "circle_orange.png")
        )

    @staticmethod
    def get_icon_running() -> QtWidgets.QIcon:
        """Get running icon.

        Returns:
            QtWidgets.QIcon: Returns "running" icon.

        """
        if ITrayService._icon_running is None:
            ITrayService._load_service_icons()
        return ITrayService._icon_running

    @staticmethod
    def get_icon_idle() -> QtWidgets.QIcon:
        """Get idle icon.

        Returns:
            QtWidgets.QIcon: Returns "idle" icon.

        """
        if ITrayService._icon_idle is None:
            ITrayService._load_service_icons()
        return ITrayService._icon_idle

    @staticmethod
    def get_icon_failed() -> QtWidgets.QIcon:
        """Get failed icon.

        Returns:
            QtWidgets.QIcon: Returns "failed" icon.

        """
        if ITrayService._icon_failed is None:
            ITrayService._load_service_icons()
        return ITrayService._icon_failed

    def tray_menu(self, tray_menu: QtWidgets.QMenu) -> None:
        """Add service to tray menu."""
        from qtpy import QtWidgets

        action = QtWidgets.QAction(
            self.label,
            self.services_submenu(tray_menu)
        )
        self.menu_action = action

        self.add_service_action(action)

        self.set_service_running_icon()

    def set_service_running_icon(self) -> None:
        """Change icon of an QAction to green circle."""
        if self.menu_action:
            self.menu_action.setIcon(self.get_icon_running())

    def set_service_failed_icon(self) -> None:
        """Change icon of an QAction to red circle."""
        if self.menu_action:
            self.menu_action.setIcon(self.get_icon_failed())

    def set_service_idle_icon(self) -> None:
        """Change icon of an QAction to orange circle."""
        if self.menu_action:
            self.menu_action.setIcon(self.get_icon_idle())

label abstractmethod property

Service label showed in menu.

add_service_action(action) staticmethod

Add service action to services submenu.

Source code in client/ayon_core/addon/interfaces.py
398
399
400
401
402
403
@staticmethod
def add_service_action(action: QtWidgets.QAction) -> None:
    """Add service action to services submenu."""
    ITrayService._services_submenu.addAction(action)
    if not ITrayService._services_submenu.menuAction().isVisible():
        ITrayService._services_submenu.menuAction().setVisible(True)

get_icon_failed() staticmethod

Get failed icon.

Returns:

Type Description
QIcon

QtWidgets.QIcon: Returns "failed" icon.

Source code in client/ayon_core/addon/interfaces.py
444
445
446
447
448
449
450
451
452
453
454
@staticmethod
def get_icon_failed() -> QtWidgets.QIcon:
    """Get failed icon.

    Returns:
        QtWidgets.QIcon: Returns "failed" icon.

    """
    if ITrayService._icon_failed is None:
        ITrayService._load_service_icons()
    return ITrayService._icon_failed

get_icon_idle() staticmethod

Get idle icon.

Returns:

Type Description
QIcon

QtWidgets.QIcon: Returns "idle" icon.

Source code in client/ayon_core/addon/interfaces.py
432
433
434
435
436
437
438
439
440
441
442
@staticmethod
def get_icon_idle() -> QtWidgets.QIcon:
    """Get idle icon.

    Returns:
        QtWidgets.QIcon: Returns "idle" icon.

    """
    if ITrayService._icon_idle is None:
        ITrayService._load_service_icons()
    return ITrayService._icon_idle

get_icon_running() staticmethod

Get running icon.

Returns:

Type Description
QIcon

QtWidgets.QIcon: Returns "running" icon.

Source code in client/ayon_core/addon/interfaces.py
420
421
422
423
424
425
426
427
428
429
430
@staticmethod
def get_icon_running() -> QtWidgets.QIcon:
    """Get running icon.

    Returns:
        QtWidgets.QIcon: Returns "running" icon.

    """
    if ITrayService._icon_running is None:
        ITrayService._load_service_icons()
    return ITrayService._icon_running

services_submenu(tray_menu) staticmethod

Get or create services submenu.

Returns:

Type Description
QMenu

QtWidgets.QMenu: Services submenu.

Source code in client/ayon_core/addon/interfaces.py
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
@staticmethod
def services_submenu(tray_menu: QtWidgets.QMenu) -> QtWidgets.QMenu:
    """Get or create services submenu.

    Returns:
        QtWidgets.QMenu: Services submenu.

    """
    if ITrayService._services_submenu is None:
        from qtpy import QtWidgets

        services_submenu = QtWidgets.QMenu("Services", tray_menu)
        services_submenu.menuAction().setVisible(False)
        ITrayService._services_submenu = services_submenu
    return ITrayService._services_submenu

set_service_failed_icon()

Change icon of an QAction to red circle.

Source code in client/ayon_core/addon/interfaces.py
475
476
477
478
def set_service_failed_icon(self) -> None:
    """Change icon of an QAction to red circle."""
    if self.menu_action:
        self.menu_action.setIcon(self.get_icon_failed())

set_service_idle_icon()

Change icon of an QAction to orange circle.

Source code in client/ayon_core/addon/interfaces.py
480
481
482
483
def set_service_idle_icon(self) -> None:
    """Change icon of an QAction to orange circle."""
    if self.menu_action:
        self.menu_action.setIcon(self.get_icon_idle())

set_service_running_icon()

Change icon of an QAction to green circle.

Source code in client/ayon_core/addon/interfaces.py
470
471
472
473
def set_service_running_icon(self) -> None:
    """Change icon of an QAction to green circle."""
    if self.menu_action:
        self.menu_action.setIcon(self.get_icon_running())

tray_menu(tray_menu)

Add service to tray menu.

Source code in client/ayon_core/addon/interfaces.py
456
457
458
459
460
461
462
463
464
465
466
467
468
def tray_menu(self, tray_menu: QtWidgets.QMenu) -> None:
    """Add service to tray menu."""
    from qtpy import QtWidgets

    action = QtWidgets.QAction(
        self.label,
        self.services_submenu(tray_menu)
    )
    self.menu_action = action

    self.add_service_action(action)

    self.set_service_running_icon()