diff --git a/client/ayon_core/hosts/houdini/api/usd.py b/client/ayon_core/hosts/houdini/api/usd.py index 443a52bc37..ed33fbf590 100644 --- a/client/ayon_core/hosts/houdini/api/usd.py +++ b/client/ayon_core/hosts/houdini/api/usd.py @@ -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 diff --git a/client/ayon_core/tools/ayon_utils/widgets/__init__.py b/client/ayon_core/tools/ayon_utils/widgets/__init__.py deleted file mode 100644 index a62bab6751..0000000000 --- a/client/ayon_core/tools/ayon_utils/widgets/__init__.py +++ /dev/null @@ -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", -) diff --git a/client/ayon_core/tools/ayon_utils/widgets/utils.py b/client/ayon_core/tools/ayon_utils/widgets/utils.py deleted file mode 100644 index ead8f4edb2..0000000000 --- a/client/ayon_core/tools/ayon_utils/widgets/utils.py +++ /dev/null @@ -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) diff --git a/client/ayon_core/tools/ayon_utils/models/__init__.py b/client/ayon_core/tools/common_models/__init__.py similarity index 100% rename from client/ayon_core/tools/ayon_utils/models/__init__.py rename to client/ayon_core/tools/common_models/__init__.py diff --git a/client/ayon_core/tools/ayon_utils/models/cache.py b/client/ayon_core/tools/common_models/cache.py similarity index 100% rename from client/ayon_core/tools/ayon_utils/models/cache.py rename to client/ayon_core/tools/common_models/cache.py diff --git a/client/ayon_core/tools/ayon_utils/models/hierarchy.py b/client/ayon_core/tools/common_models/hierarchy.py similarity index 100% rename from client/ayon_core/tools/ayon_utils/models/hierarchy.py rename to client/ayon_core/tools/common_models/hierarchy.py diff --git a/client/ayon_core/tools/ayon_utils/models/projects.py b/client/ayon_core/tools/common_models/projects.py similarity index 100% rename from client/ayon_core/tools/ayon_utils/models/projects.py rename to client/ayon_core/tools/common_models/projects.py diff --git a/client/ayon_core/tools/ayon_utils/models/selection.py b/client/ayon_core/tools/common_models/selection.py similarity index 100% rename from client/ayon_core/tools/ayon_utils/models/selection.py rename to client/ayon_core/tools/common_models/selection.py diff --git a/client/ayon_core/tools/ayon_utils/models/thumbnails.py b/client/ayon_core/tools/common_models/thumbnails.py similarity index 100% rename from client/ayon_core/tools/ayon_utils/models/thumbnails.py rename to client/ayon_core/tools/common_models/thumbnails.py diff --git a/client/ayon_core/tools/context_dialog/window.py b/client/ayon_core/tools/context_dialog/window.py index b145e77515..828d771142 100644 --- a/client/ayon_core/tools/context_dialog/window.py +++ b/client/ayon_core/tools/context_dialog/window.py @@ -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): diff --git a/client/ayon_core/tools/launcher/control.py b/client/ayon_core/tools/launcher/control.py index 8780b211f1..abd0cd78d8 100644 --- a/client/ayon_core/tools/launcher/control.py +++ b/client/ayon_core/tools/launcher/control.py @@ -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 diff --git a/client/ayon_core/tools/launcher/ui/actions_widget.py b/client/ayon_core/tools/launcher/ui/actions_widget.py index 617f3b0c91..a225827418 100644 --- a/client/ayon_core/tools/launcher/ui/actions_widget.py +++ b/client/ayon_core/tools/launcher/ui/actions_widget.py @@ -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 diff --git a/client/ayon_core/tools/launcher/ui/hierarchy_page.py b/client/ayon_core/tools/launcher/ui/hierarchy_page.py index 5b5f88a802..226a57930b 100644 --- a/client/ayon_core/tools/launcher/ui/hierarchy_page.py +++ b/client/ayon_core/tools/launcher/ui/hierarchy_page.py @@ -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, diff --git a/client/ayon_core/tools/launcher/ui/projects_widget.py b/client/ayon_core/tools/launcher/ui/projects_widget.py index 729caf3232..e2af54b55d 100644 --- a/client/ayon_core/tools/launcher/ui/projects_widget.py +++ b/client/ayon_core/tools/launcher/ui/projects_widget.py @@ -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): diff --git a/client/ayon_core/tools/loader/control.py b/client/ayon_core/tools/loader/control.py index 5995bd2cae..d8562f50ca 100644 --- a/client/ayon_core/tools/loader/control.py +++ b/client/ayon_core/tools/loader/control.py @@ -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, diff --git a/client/ayon_core/tools/loader/models/actions.py b/client/ayon_core/tools/loader/models/actions.py index aab5ba49d1..ad2993af50 100644 --- a/client/ayon_core/tools/loader/models/actions.py +++ b/client/ayon_core/tools/loader/models/actions.py @@ -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" diff --git a/client/ayon_core/tools/loader/models/products.py b/client/ayon_core/tools/loader/models/products.py index 63547bef8b..812446a012 100644 --- a/client/ayon_core/tools/loader/models/products.py +++ b/client/ayon_core/tools/loader/models/products.py @@ -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, diff --git a/client/ayon_core/tools/loader/models/site_sync.py b/client/ayon_core/tools/loader/models/site_sync.py index daa9f7ba50..a589cf7fbe 100644 --- a/client/ayon_core/tools/loader/models/site_sync.py +++ b/client/ayon_core/tools/loader/models/site_sync.py @@ -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" diff --git a/client/ayon_core/tools/loader/ui/actions_utils.py b/client/ayon_core/tools/loader/ui/actions_utils.py index bf6ab6eeb5..5a988ef4c2 100644 --- a/client/ayon_core/tools/loader/ui/actions_utils.py +++ b/client/ayon_core/tools/loader/ui/actions_utils.py @@ -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): diff --git a/client/ayon_core/tools/loader/ui/folders_widget.py b/client/ayon_core/tools/loader/ui/folders_widget.py index 34881ab49d..7b146456da 100644 --- a/client/ayon_core/tools/loader/ui/folders_widget.py +++ b/client/ayon_core/tools/loader/ui/folders_widget.py @@ -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 diff --git a/client/ayon_core/tools/loader/ui/product_types_widget.py b/client/ayon_core/tools/loader/ui/product_types_widget.py index 26244517ec..180994fd7f 100644 --- a/client/ayon_core/tools/loader/ui/product_types_widget.py +++ b/client/ayon_core/tools/loader/ui/product_types_widget.py @@ -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 diff --git a/client/ayon_core/tools/loader/ui/products_model.py b/client/ayon_core/tools/loader/ui/products_model.py index 331efad68a..c51172849a 100644 --- a/client/ayon_core/tools/loader/ui/products_model.py +++ b/client/ayon_core/tools/loader/ui/products_model.py @@ -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" diff --git a/client/ayon_core/tools/loader/ui/repres_widget.py b/client/ayon_core/tools/loader/ui/repres_widget.py index 27db8dda40..3b6b8f94bf 100644 --- a/client/ayon_core/tools/loader/ui/repres_widget.py +++ b/client/ayon_core/tools/loader/ui/repres_widget.py @@ -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 diff --git a/client/ayon_core/tools/loader/ui/window.py b/client/ayon_core/tools/loader/ui/window.py index 104b64d81c..3a6f4679fa 100644 --- a/client/ayon_core/tools/loader/ui/window.py +++ b/client/ayon_core/tools/loader/ui/window.py @@ -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 diff --git a/client/ayon_core/tools/publisher/control.py b/client/ayon_core/tools/publisher/control.py index aaca0fea10..ede772b917 100644 --- a/client/ayon_core/tools/publisher/control.py +++ b/client/ayon_core/tools/publisher/control.py @@ -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 diff --git a/client/ayon_core/tools/publisher/widgets/create_context_widgets.py b/client/ayon_core/tools/publisher/widgets/create_context_widgets.py index d65a2ace8d..61223bbe75 100644 --- a/client/ayon_core/tools/publisher/widgets/create_context_widgets.py +++ b/client/ayon_core/tools/publisher/widgets/create_context_widgets.py @@ -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): diff --git a/client/ayon_core/tools/publisher/widgets/folders_dialog.py b/client/ayon_core/tools/publisher/widgets/folders_dialog.py index 8f93264b2e..03336e10a6 100644 --- a/client/ayon_core/tools/publisher/widgets/folders_dialog.py +++ b/client/ayon_core/tools/publisher/widgets/folders_dialog.py @@ -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: diff --git a/client/ayon_core/tools/publisher/widgets/tasks_model.py b/client/ayon_core/tools/publisher/widgets/tasks_model.py index 8f00dc37a2..e36de80fcf 100644 --- a/client/ayon_core/tools/publisher/widgets/tasks_model.py +++ b/client/ayon_core/tools/publisher/widgets/tasks_model.py @@ -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) diff --git a/client/ayon_core/tools/push_to_project/control.py b/client/ayon_core/tools/push_to_project/control.py index d5acaadc2a..58447a8389 100644 --- a/client/ayon_core/tools/push_to_project/control.py +++ b/client/ayon_core/tools/push_to_project/control.py @@ -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, diff --git a/client/ayon_core/tools/push_to_project/ui/window.py b/client/ayon_core/tools/push_to_project/ui/window.py index bc2fc6bf96..4d64509afd 100644 --- a/client/ayon_core/tools/push_to_project/ui/window.py +++ b/client/ayon_core/tools/push_to_project/ui/window.py @@ -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, diff --git a/client/ayon_core/tools/sceneinventory/control.py b/client/ayon_core/tools/sceneinventory/control.py index 16b889e855..77f4d60b22 100644 --- a/client/ayon_core/tools/sceneinventory/control.py +++ b/client/ayon_core/tools/sceneinventory/control.py @@ -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 diff --git a/client/ayon_core/tools/sceneinventory/model.py b/client/ayon_core/tools/sceneinventory/model.py index e53b6aa4c3..df0dea7a3d 100644 --- a/client/ayon_core/tools/sceneinventory/model.py +++ b/client/ayon_core/tools/sceneinventory/model.py @@ -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): diff --git a/client/ayon_core/tools/sceneinventory/switch_dialog/folders_input.py b/client/ayon_core/tools/sceneinventory/switch_dialog/folders_input.py index e46c28474f..3137e70214 100644 --- a/client/ayon_core/tools/sceneinventory/switch_dialog/folders_input.py +++ b/client/ayon_core/tools/sceneinventory/switch_dialog/folders_input.py @@ -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() diff --git a/client/ayon_core/tools/traypublisher/window.py b/client/ayon_core/tools/traypublisher/window.py index 988c22819a..4700e20531 100644 --- a/client/ayon_core/tools/traypublisher/window.py +++ b/client/ayon_core/tools/traypublisher/window.py @@ -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, diff --git a/client/ayon_core/tools/utils/__init__.py b/client/ayon_core/tools/utils/__init__.py index 445b4d9b97..4b5fbeaf67 100644 --- a/client/ayon_core/tools/utils/__init__.py +++ b/client/ayon_core/tools/utils/__init__.py @@ -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", ) diff --git a/client/ayon_core/tools/ayon_utils/widgets/folders_widget.py b/client/ayon_core/tools/utils/folders_widget.py similarity index 99% rename from client/ayon_core/tools/ayon_utils/widgets/folders_widget.py rename to client/ayon_core/tools/utils/folders_widget.py index e42a5b635c..2ad640de37 100644 --- a/client/ayon_core/tools/ayon_utils/widgets/folders_widget.py +++ b/client/ayon_core/tools/utils/folders_widget.py @@ -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 diff --git a/client/ayon_core/tools/utils/lib.py b/client/ayon_core/tools/utils/lib.py index 741fc1f335..8bcfe8b985 100644 --- a/client/ayon_core/tools/utils/lib.py +++ b/client/ayon_core/tools/utils/lib.py @@ -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) diff --git a/client/ayon_core/tools/ayon_utils/widgets/projects_widget.py b/client/ayon_core/tools/utils/projects_widget.py similarity index 99% rename from client/ayon_core/tools/ayon_utils/widgets/projects_widget.py rename to client/ayon_core/tools/utils/projects_widget.py index 79ffc77640..fd361493ab 100644 --- a/client/ayon_core/tools/ayon_utils/widgets/projects_widget.py +++ b/client/ayon_core/tools/utils/projects_widget.py @@ -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 diff --git a/client/ayon_core/tools/ayon_utils/widgets/tasks_widget.py b/client/ayon_core/tools/utils/tasks_widget.py similarity index 99% rename from client/ayon_core/tools/ayon_utils/widgets/tasks_widget.py rename to client/ayon_core/tools/utils/tasks_widget.py index cfe901c492..0ff8e8a5c1 100644 --- a/client/ayon_core/tools/ayon_utils/widgets/tasks_widget.py +++ b/client/ayon_core/tools/utils/tasks_widget.py @@ -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 diff --git a/client/ayon_core/tools/workfiles/control.py b/client/ayon_core/tools/workfiles/control.py index 3111c4d443..7fa7af1662 100644 --- a/client/ayon_core/tools/workfiles/control.py +++ b/client/ayon_core/tools/workfiles/control.py @@ -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, diff --git a/client/ayon_core/tools/workfiles/widgets/window.py b/client/ayon_core/tools/workfiles/widgets/window.py index 86a84b6195..8a2617d270 100644 --- a/client/ayon_core/tools/workfiles/widgets/window.py +++ b/client/ayon_core/tools/workfiles/widgets/window.py @@ -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