Merge pull request #195 from ynput/enhancement/AY-3670_Move-models-and-widgets-from-ayon_utils

Tools: Move ayon utils to correct place
This commit is contained in:
Jakub Trllo 2024-03-18 18:27:47 +01:00 committed by GitHub
commit ebbacdee94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 258 additions and 258 deletions

View file

@ -8,8 +8,11 @@ from qtpy import QtWidgets, QtCore, QtGui
from ayon_core import style
from ayon_core.pipeline import get_current_project_name
from ayon_core.tools.utils import PlaceholderLineEdit, RefreshButton
from ayon_core.tools.ayon_utils.widgets import SimpleFoldersWidget
from ayon_core.tools.utils import (
PlaceholderLineEdit,
RefreshButton,
SimpleFoldersWidget,
)
from pxr import Sdf

View file

@ -1,51 +0,0 @@
from .projects_widget import (
# ProjectsWidget,
ProjectsCombobox,
ProjectsQtModel,
ProjectSortFilterProxy,
PROJECT_NAME_ROLE,
PROJECT_IS_CURRENT_ROLE,
PROJECT_IS_ACTIVE_ROLE,
PROJECT_IS_LIBRARY_ROLE,
)
from .folders_widget import (
FoldersWidget,
FoldersQtModel,
FOLDERS_MODEL_SENDER_NAME,
SimpleFoldersWidget,
)
from .tasks_widget import (
TasksWidget,
TasksQtModel,
TASKS_MODEL_SENDER_NAME,
)
from .utils import (
get_qt_icon,
RefreshThread,
)
__all__ = (
# "ProjectsWidget",
"ProjectsCombobox",
"ProjectsQtModel",
"ProjectSortFilterProxy",
"PROJECT_NAME_ROLE",
"PROJECT_IS_CURRENT_ROLE",
"PROJECT_IS_ACTIVE_ROLE",
"PROJECT_IS_LIBRARY_ROLE",
"FoldersWidget",
"FoldersQtModel",
"FOLDERS_MODEL_SENDER_NAME",
"SimpleFoldersWidget",
"TasksWidget",
"TasksQtModel",
"TASKS_MODEL_SENDER_NAME",
"get_qt_icon",
"RefreshThread",
)

View file

@ -1,109 +0,0 @@
import os
from functools import partial
from qtpy import QtCore, QtGui
from ayon_core.tools.utils.lib import get_qta_icon_by_name_and_color
class RefreshThread(QtCore.QThread):
refresh_finished = QtCore.Signal(str)
def __init__(self, thread_id, func, *args, **kwargs):
super(RefreshThread, self).__init__()
self._id = thread_id
self._callback = partial(func, *args, **kwargs)
self._exception = None
self._result = None
self.finished.connect(self._on_finish_callback)
@property
def id(self):
return self._id
@property
def failed(self):
return self._exception is not None
def run(self):
try:
self._result = self._callback()
except Exception as exc:
self._exception = exc
def get_result(self):
return self._result
def _on_finish_callback(self):
"""Trigger custom signal with thread id.
Listening for 'finished' signal we make sure that execution of thread
finished and QThread object can be safely deleted.
"""
self.refresh_finished.emit(self.id)
class _IconsCache:
"""Cache for icons."""
_cache = {}
_default = None
@classmethod
def _get_cache_key(cls, icon_def):
parts = []
icon_type = icon_def["type"]
if icon_type == "path":
parts = [icon_type, icon_def["path"]]
elif icon_type == "awesome-font":
parts = [icon_type, icon_def["name"], icon_def["color"]]
return "|".join(parts)
@classmethod
def get_icon(cls, icon_def):
if not icon_def:
return None
icon_type = icon_def["type"]
cache_key = cls._get_cache_key(icon_def)
cache = cls._cache.get(cache_key)
if cache is not None:
return cache
icon = None
if icon_type == "path":
path = icon_def["path"]
if os.path.exists(path):
icon = QtGui.QIcon(path)
elif icon_type == "awesome-font":
icon_name = icon_def["name"]
icon_color = icon_def["color"]
icon = get_qta_icon_by_name_and_color(icon_name, icon_color)
if icon is None:
icon = get_qta_icon_by_name_and_color(
"fa.{}".format(icon_name), icon_color)
if icon is None:
icon = cls.get_default()
cls._cache[cache_key] = icon
return icon
@classmethod
def get_default(cls):
pix = QtGui.QPixmap(1, 1)
pix.fill(QtCore.Qt.transparent)
return QtGui.QIcon(pix)
def get_qt_icon(icon_def):
"""Returns icon from cache or creates new one.
Args:
icon_def (dict[str, Any]): Icon definition.
Returns:
QtGui.QIcon: Icon.
"""
return _IconsCache.get_icon(icon_def)

View file

@ -6,19 +6,17 @@ from qtpy import QtWidgets, QtCore, QtGui
from ayon_core import style
from ayon_core.lib.events import QueuedEventSystem
from ayon_core.tools.ayon_utils.models import (
from ayon_core.tools.common_models import (
ProjectsModel,
HierarchyModel,
)
from ayon_core.tools.ayon_utils.widgets import (
from ayon_core.tools.utils import (
ProjectsCombobox,
FoldersWidget,
TasksWidget,
)
from ayon_core.tools.utils.lib import (
center_window,
get_ayon_qt_app,
)
from ayon_core.tools.utils.lib import center_window
class SelectionModel(object):

View file

@ -1,7 +1,7 @@
from ayon_core.lib import Logger
from ayon_core.lib.events import QueuedEventSystem
from ayon_core.settings import get_project_settings
from ayon_core.tools.ayon_utils.models import ProjectsModel, HierarchyModel
from ayon_core.tools.common_models import ProjectsModel, HierarchyModel
from .abstract import AbstractLauncherFrontEnd, AbstractLauncherBackend
from .models import LauncherSelectionModel, ActionsModel

View file

@ -4,7 +4,7 @@ import collections
from qtpy import QtWidgets, QtCore, QtGui
from ayon_core.tools.flickcharm import FlickCharm
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
from ayon_core.tools.utils import get_qt_icon
from .resources import get_options_image_path

View file

@ -6,7 +6,7 @@ from ayon_core.tools.utils import (
SquareButton,
RefreshButton,
)
from ayon_core.tools.ayon_utils.widgets import (
from ayon_core.tools.utils import (
ProjectsCombobox,
FoldersWidget,
TasksWidget,

View file

@ -1,12 +1,13 @@
from qtpy import QtWidgets, QtCore
from ayon_core.tools.flickcharm import FlickCharm
from ayon_core.tools.utils import PlaceholderLineEdit, RefreshButton
from ayon_core.tools.ayon_utils.widgets import (
from ayon_core.tools.utils import (
PlaceholderLineEdit,
RefreshButton,
ProjectsQtModel,
ProjectSortFilterProxy,
)
from ayon_core.tools.ayon_utils.models import PROJECTS_MODEL_SENDER
from ayon_core.tools.common_models import PROJECTS_MODEL_SENDER
class ProjectIconView(QtWidgets.QListView):

View file

@ -6,7 +6,7 @@ import ayon_api
from ayon_core.lib.events import QueuedEventSystem
from ayon_core.pipeline import Anatomy, get_current_context
from ayon_core.host import ILoadHost
from ayon_core.tools.ayon_utils.models import (
from ayon_core.tools.common_models import (
ProjectsModel,
HierarchyModel,
NestedCacheItem,

View file

@ -17,7 +17,7 @@ from ayon_core.pipeline.load import (
LoadError,
IncompatibleLoaderError,
)
from ayon_core.tools.ayon_utils.models import NestedCacheItem
from ayon_core.tools.common_models import NestedCacheItem
from ayon_core.tools.loader.abstract import ActionItem
ACTIONS_MODEL_SENDER = "actions.model"

View file

@ -6,7 +6,7 @@ import ayon_api
from ayon_api.operations import OperationsSession
from ayon_core.style import get_default_entity_icon_color
from ayon_core.tools.ayon_utils.models import NestedCacheItem
from ayon_core.tools.common_models import NestedCacheItem
from ayon_core.tools.loader.abstract import (
ProductTypeItem,
ProductItem,

View file

@ -4,7 +4,7 @@ from ayon_api import get_representations, get_versions_links
from ayon_core.lib import Logger
from ayon_core.addon import AddonsManager
from ayon_core.tools.ayon_utils.models import NestedCacheItem
from ayon_core.tools.common_models import NestedCacheItem
from ayon_core.tools.loader.abstract import ActionItem
DOWNLOAD_IDENTIFIER = "sitesync.download"

View file

@ -10,7 +10,7 @@ from ayon_core.tools.utils.widgets import (
OptionalAction,
OptionDialog,
)
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
from ayon_core.tools.utils import get_qt_icon
def show_actions_menu(action_items, global_point, one_item_selected, parent):

View file

@ -7,11 +7,11 @@ from ayon_core.tools.utils import (
)
from ayon_core.style import get_objected_colors
from ayon_core.tools.ayon_utils.widgets import (
from ayon_core.tools.utils import (
FoldersQtModel,
FOLDERS_MODEL_SENDER_NAME,
)
from ayon_core.tools.ayon_utils.widgets.folders_widget import FOLDER_ID_ROLE
from ayon_core.tools.utils.folders_widget import FOLDER_ID_ROLE
if qtpy.API == "pyside":
from PySide.QtGui import QStyleOptionViewItemV4

View file

@ -1,6 +1,6 @@
from qtpy import QtWidgets, QtGui, QtCore
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
from ayon_core.tools.utils import get_qt_icon
PRODUCT_TYPE_ROLE = QtCore.Qt.UserRole + 1

View file

@ -4,7 +4,7 @@ import qtawesome
from qtpy import QtGui, QtCore
from ayon_core.style import get_default_entity_icon_color
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
from ayon_core.tools.utils import get_qt_icon
PRODUCTS_MODEL_SENDER_NAME = "qt_products_model"

View file

@ -4,7 +4,7 @@ from qtpy import QtWidgets, QtGui, QtCore
import qtawesome
from ayon_core.style import get_default_entity_icon_color
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
from ayon_core.tools.utils import get_qt_icon
from ayon_core.tools.utils import DeselectableTreeView
from .actions_utils import show_actions_menu

View file

@ -10,7 +10,7 @@ from ayon_core.tools.utils import (
GoToCurrentButton,
)
from ayon_core.tools.utils.lib import center_window
from ayon_core.tools.ayon_utils.widgets import ProjectsCombobox
from ayon_core.tools.utils import ProjectsCombobox
from ayon_core.tools.loader.control import LoaderController
from .folders_widget import LoaderFoldersWidget

View file

@ -38,7 +38,7 @@ from ayon_core.pipeline.create.context import (
ConvertorsOperationFailed,
)
from ayon_core.pipeline.publish import get_publish_instance_label
from ayon_core.tools.ayon_utils.models import HierarchyModel
from ayon_core.tools.common_models import HierarchyModel
# Define constant for plugin orders offset
PLUGIN_ORDER_OFFSET = 0.5

View file

@ -3,8 +3,8 @@ from qtpy import QtWidgets, QtCore, QtGui
from ayon_core.lib.events import QueuedEventSystem
from ayon_core.tools.utils import PlaceholderLineEdit, GoToCurrentButton
from ayon_core.tools.ayon_utils.models import HierarchyExpectedSelection
from ayon_core.tools.ayon_utils.widgets import FoldersWidget, TasksWidget
from ayon_core.tools.common_models import HierarchyExpectedSelection
from ayon_core.tools.utils import FoldersWidget, TasksWidget
class CreateSelectionModel(object):

View file

@ -1,8 +1,7 @@
from qtpy import QtWidgets, QtCore, QtGui
from ayon_core.lib.events import QueuedEventSystem
from ayon_core.tools.ayon_utils.widgets import FoldersWidget
from ayon_core.tools.utils import PlaceholderLineEdit
from ayon_core.tools.utils import PlaceholderLineEdit, FoldersWidget
class FoldersDialogController:

View file

@ -1,6 +1,7 @@
from qtpy import QtWidgets, QtCore, QtGui
from ayon_core.tools.utils.lib import get_default_task_icon
from ayon_core.style import get_default_entity_icon_color
from ayon_core.tools.utils import get_qt_icon
TASK_NAME_ROLE = QtCore.Qt.UserRole + 1
TASK_TYPE_ROLE = QtCore.Qt.UserRole + 2
@ -121,6 +122,11 @@ class TasksModel(QtGui.QStandardItemModel):
item = self._items_by_name.pop(task_name)
root_item.removeRow(item.row())
icon = get_qt_icon({
"type": "awesome-font",
"name": "fa.male",
"color": get_default_entity_icon_color(),
})
new_items = []
for task_name in new_task_names:
if task_name in self._items_by_name:
@ -129,7 +135,7 @@ class TasksModel(QtGui.QStandardItemModel):
item = QtGui.QStandardItem(task_name)
item.setData(task_name, TASK_NAME_ROLE)
if task_name:
item.setData(get_default_task_icon(), QtCore.Qt.DecorationRole)
item.setData(icon, QtCore.Qt.DecorationRole)
self._items_by_name[task_name] = item
new_items.append(item)

View file

@ -6,7 +6,7 @@ from ayon_core.settings import get_project_settings
from ayon_core.lib import prepare_template_data
from ayon_core.lib.events import QueuedEventSystem
from ayon_core.pipeline.create import get_product_name_template
from ayon_core.tools.ayon_utils.models import ProjectsModel, HierarchyModel
from ayon_core.tools.common_models import ProjectsModel, HierarchyModel
from .models import (
PushToProjectSelectionModel,

View file

@ -5,8 +5,6 @@ from ayon_core.tools.utils import (
PlaceholderLineEdit,
SeparatorWidget,
set_style_property,
)
from ayon_core.tools.ayon_utils.widgets import (
ProjectsCombobox,
FoldersWidget,
TasksWidget,

View file

@ -6,7 +6,7 @@ from ayon_core.pipeline import (
registered_host,
get_current_context,
)
from ayon_core.tools.ayon_utils.models import HierarchyModel
from ayon_core.tools.common_models import HierarchyModel
from .models import SiteSyncModel

View file

@ -13,8 +13,8 @@ from ayon_core.pipeline import (
HeroVersionType,
)
from ayon_core.style import get_default_entity_icon_color
from ayon_core.tools.utils import get_qt_icon
from ayon_core.tools.utils.models import TreeModel, Item
from ayon_core.tools.ayon_utils.widgets import get_qt_icon
def walk_hierarchy(node):

View file

@ -5,8 +5,8 @@ from ayon_core.tools.utils import (
PlaceholderLineEdit,
BaseClickableFrame,
set_style_property,
FoldersWidget,
)
from ayon_core.tools.ayon_utils.widgets import FoldersWidget
NOT_SET = object()

View file

@ -16,9 +16,10 @@ from ayon_core.pipeline import install_host
from ayon_core.hosts.traypublisher.api import TrayPublisherHost
from ayon_core.tools.publisher.control_qt import QtPublisherController
from ayon_core.tools.publisher.window import PublisherWindow
from ayon_core.tools.utils import PlaceholderLineEdit, get_ayon_qt_app
from ayon_core.tools.ayon_utils.models import ProjectsModel
from ayon_core.tools.ayon_utils.widgets import (
from ayon_core.tools.common_models import ProjectsModel
from ayon_core.tools.utils import (
PlaceholderLineEdit,
get_ayon_qt_app,
ProjectsQtModel,
ProjectSortFilterProxy,
PROJECT_NAME_ROLE,

View file

@ -37,6 +37,7 @@ from .lib import (
get_qt_app,
get_ayon_qt_app,
get_openpype_qt_app,
get_qt_icon,
)
from .models import (
@ -55,6 +56,28 @@ from .dialogs import (
SimplePopup,
PopupUpdateKeys,
)
from .projects_widget import (
ProjectsCombobox,
ProjectsQtModel,
ProjectSortFilterProxy,
PROJECT_NAME_ROLE,
PROJECT_IS_CURRENT_ROLE,
PROJECT_IS_ACTIVE_ROLE,
PROJECT_IS_LIBRARY_ROLE,
)
from .folders_widget import (
FoldersWidget,
FoldersQtModel,
FOLDERS_MODEL_SENDER_NAME,
SimpleFoldersWidget,
)
from .tasks_widget import (
TasksWidget,
TasksQtModel,
TASKS_MODEL_SENDER_NAME,
)
__all__ = (
@ -96,6 +119,7 @@ __all__ = (
"get_qt_app",
"get_ayon_qt_app",
"get_openpype_qt_app",
"get_qt_icon",
"RecursiveSortFilterProxyModel",
@ -113,4 +137,21 @@ __all__ = (
"ScrollMessageBox",
"SimplePopup",
"PopupUpdateKeys",
"ProjectsCombobox",
"ProjectsQtModel",
"ProjectSortFilterProxy",
"PROJECT_NAME_ROLE",
"PROJECT_IS_CURRENT_ROLE",
"PROJECT_IS_ACTIVE_ROLE",
"PROJECT_IS_LIBRARY_ROLE",
"FoldersWidget",
"FoldersQtModel",
"FOLDERS_MODEL_SENDER_NAME",
"SimpleFoldersWidget",
"TasksWidget",
"TasksQtModel",
"TASKS_MODEL_SENDER_NAME",
)

View file

@ -3,16 +3,15 @@ import collections
from qtpy import QtWidgets, QtGui, QtCore
from ayon_core.lib.events import QueuedEventSystem
from ayon_core.tools.ayon_utils.models import (
from ayon_core.tools.common_models import (
HierarchyModel,
HierarchyExpectedSelection,
)
from ayon_core.tools.utils import (
RecursiveSortFilterProxyModel,
TreeView,
)
from .utils import RefreshThread, get_qt_icon
from .models import RecursiveSortFilterProxyModel
from .views import TreeView
from .lib import RefreshThread, get_qt_icon
FOLDERS_MODEL_SENDER_NAME = "qt_folders_model"
FOLDER_ID_ROLE = QtCore.Qt.UserRole + 1

View file

@ -1,6 +1,7 @@
import os
import sys
import contextlib
from functools import partial
from qtpy import QtWidgets, QtCore, QtGui
import qtawesome
@ -195,51 +196,6 @@ def get_openpype_qt_app():
return get_ayon_qt_app()
class _Cache:
icons = {}
def get_qta_icon_by_name_and_color(icon_name, icon_color):
if not icon_name or not icon_color:
return None
full_icon_name = "{0}-{1}".format(icon_name, icon_color)
if full_icon_name in _Cache.icons:
return _Cache.icons[full_icon_name]
variants = [icon_name]
qta_instance = qtawesome._instance()
for key in qta_instance.charmap.keys():
variants.append("{0}.{1}".format(key, icon_name))
icon = None
used_variant = None
for variant in variants:
try:
icon = qtawesome.icon(variant, color=icon_color)
used_variant = variant
break
except Exception:
pass
if used_variant is None:
log.info("Didn't find icon \"{}\"".format(icon_name))
elif used_variant != icon_name:
log.debug("Icon \"{}\" was not found \"{}\" is used instead".format(
icon_name, used_variant
))
_Cache.icons[full_icon_name] = icon
return icon
def get_default_task_icon(color=None):
if color is None:
color = get_default_entity_icon_color()
return get_qta_icon_by_name_and_color("fa.male", color)
def iter_model_rows(model, column, include_root=False):
"""Iterate over all row indices in a model"""
indices = [QtCore.QModelIndex()] # start iteration at root
@ -457,3 +413,156 @@ def get_warning_pixmap(color=None):
color = get_objected_colors("delete-btn-bg").get_qcolor()
return paint_image_with_color(src_image, color)
class RefreshThread(QtCore.QThread):
refresh_finished = QtCore.Signal(str)
def __init__(self, thread_id, func, *args, **kwargs):
super(RefreshThread, self).__init__()
self._id = thread_id
self._callback = partial(func, *args, **kwargs)
self._exception = None
self._result = None
self.finished.connect(self._on_finish_callback)
@property
def id(self):
return self._id
@property
def failed(self):
return self._exception is not None
def run(self):
try:
self._result = self._callback()
except Exception as exc:
self._exception = exc
def get_result(self):
return self._result
def _on_finish_callback(self):
"""Trigger custom signal with thread id.
Listening for 'finished' signal we make sure that execution of thread
finished and QThread object can be safely deleted.
"""
self.refresh_finished.emit(self.id)
class _IconsCache:
"""Cache for icons."""
_cache = {}
_default = None
_qtawesome_cache = {}
@classmethod
def _get_cache_key(cls, icon_def):
parts = []
icon_type = icon_def["type"]
if icon_type == "path":
parts = [icon_type, icon_def["path"]]
elif icon_type == "awesome-font":
parts = [icon_type, icon_def["name"], icon_def["color"]]
return "|".join(parts)
@classmethod
def get_icon(cls, icon_def):
if not icon_def:
return None
icon_type = icon_def["type"]
cache_key = cls._get_cache_key(icon_def)
cache = cls._cache.get(cache_key)
if cache is not None:
return cache
icon = None
if icon_type == "path":
path = icon_def["path"]
if os.path.exists(path):
icon = QtGui.QIcon(path)
elif icon_type == "awesome-font":
icon_name = icon_def["name"]
icon_color = icon_def["color"]
icon = cls.get_qta_icon_by_name_and_color(icon_name, icon_color)
if icon is None:
icon = cls.get_qta_icon_by_name_and_color(
"fa.{}".format(icon_name), icon_color)
if icon is None:
icon = cls.get_default()
cls._cache[cache_key] = icon
return icon
@classmethod
def get_default(cls):
pix = QtGui.QPixmap(1, 1)
pix.fill(QtCore.Qt.transparent)
return QtGui.QIcon(pix)
@classmethod
def get_qta_icon_by_name_and_color(cls, icon_name, icon_color):
if not icon_name or not icon_color:
return None
full_icon_name = "{0}-{1}".format(icon_name, icon_color)
if full_icon_name in cls._qtawesome_cache:
return cls._qtawesome_cache[full_icon_name]
variants = [icon_name]
qta_instance = qtawesome._instance()
for key in qta_instance.charmap.keys():
variants.append("{0}.{1}".format(key, icon_name))
icon = None
used_variant = None
for variant in variants:
try:
icon = qtawesome.icon(variant, color=icon_color)
used_variant = variant
break
except Exception:
pass
if used_variant is None:
log.info("Didn't find icon \"{}\"".format(icon_name))
elif used_variant != icon_name:
log.debug("Icon \"{}\" was not found \"{}\" is used instead".format(
icon_name, used_variant
))
cls._qtawesome_cache[full_icon_name] = icon
return icon
def get_qt_icon(icon_def):
"""Returns icon from cache or creates new one.
Args:
icon_def (dict[str, Any]): Icon definition.
Returns:
QtGui.QIcon: Icon.
"""
return _IconsCache.get_icon(icon_def)
def get_qta_icon_by_name_and_color(icon_name, icon_color):
"""Returns icon from cache or creates new one.
Args:
icon_name (str): Icon name.
icon_color (str): Icon color.
Returns:
QtGui.QIcon: Icon.
"""
return _IconsCache.get_qta_icon_by_name_and_color(icon_name, icon_color)

View file

@ -1,7 +1,8 @@
from qtpy import QtWidgets, QtCore, QtGui
from ayon_core.tools.ayon_utils.models import PROJECTS_MODEL_SENDER
from .utils import RefreshThread, get_qt_icon
from ayon_core.tools.common_models import PROJECTS_MODEL_SENDER
from .lib import RefreshThread, get_qt_icon
PROJECT_NAME_ROLE = QtCore.Qt.UserRole + 1
PROJECT_IS_ACTIVE_ROLE = QtCore.Qt.UserRole + 2

View file

@ -1,9 +1,9 @@
from qtpy import QtWidgets, QtGui, QtCore
from ayon_core.style import get_disabled_entity_icon_color
from ayon_core.tools.utils import DeselectableTreeView
from .utils import RefreshThread, get_qt_icon
from .views import DeselectableTreeView
from .lib import RefreshThread, get_qt_icon
TASKS_MODEL_SENDER_NAME = "qt_tasks_model"
ITEM_ID_ROLE = QtCore.Qt.UserRole + 1

View file

@ -15,7 +15,7 @@ from ayon_core.pipeline.context_tools import (
)
from ayon_core.pipeline.workfile import create_workdir_extra_folders
from ayon_core.tools.ayon_utils.models import (
from ayon_core.tools.common_models import (
HierarchyModel,
HierarchyExpectedSelection,
ProjectsModel,

View file

@ -6,9 +6,13 @@ from ayon_core.tools.utils import (
MessageOverlayObject,
)
from ayon_core.tools.ayon_utils.widgets import FoldersWidget, TasksWidget
from ayon_core.tools.workfiles.control import BaseWorkfileController
from ayon_core.tools.utils import GoToCurrentButton, RefreshButton
from ayon_core.tools.utils import (
GoToCurrentButton,
RefreshButton,
FoldersWidget,
TasksWidget,
)
from .side_panel import SidePanelWidget
from .files_widget import FilesWidget