mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 12:54:40 +01:00
Merge branch 'develop' into bugfix-linked-assets-regex
This commit is contained in:
commit
90d2e341ad
19 changed files with 405 additions and 175 deletions
|
|
@ -75,6 +75,7 @@ class CreateHeroVersion(load.ProductLoaderPlugin):
|
|||
msgBox.setStyleSheet(style.load_stylesheet())
|
||||
msgBox.setWindowFlags(
|
||||
msgBox.windowFlags() | QtCore.Qt.WindowType.FramelessWindowHint
|
||||
| QtCore.Qt.WindowType.WindowStaysOnTopHint
|
||||
)
|
||||
msgBox.exec_()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
import json
|
||||
import collections
|
||||
from typing import Optional
|
||||
|
||||
import ayon_api
|
||||
from ayon_api.graphql import FIELD_VALUE, GraphQlQuery, fields_to_dict
|
||||
|
||||
from ayon_core.lib import NestedCacheItem
|
||||
from ayon_core.lib import NestedCacheItem, get_ayon_username
|
||||
|
||||
NOT_SET = object()
|
||||
|
||||
|
||||
# --- Implementation that should be in ayon-python-api ---
|
||||
|
|
@ -105,9 +108,18 @@ class UserItem:
|
|||
|
||||
class UsersModel:
|
||||
def __init__(self, controller):
|
||||
self._current_username = NOT_SET
|
||||
self._controller = controller
|
||||
self._users_cache = NestedCacheItem(default_factory=list)
|
||||
|
||||
def get_current_username(self) -> Optional[str]:
|
||||
if self._current_username is NOT_SET:
|
||||
self._current_username = get_ayon_username()
|
||||
return self._current_username
|
||||
|
||||
def reset(self) -> None:
|
||||
self._users_cache.reset()
|
||||
|
||||
def get_user_items(self, project_name):
|
||||
"""Get user items.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
from typing import Optional
|
||||
|
||||
from ayon_core.lib import Logger, get_ayon_username
|
||||
from ayon_core.lib import Logger
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.addon import AddonsManager
|
||||
from ayon_core.settings import get_project_settings, get_studio_settings
|
||||
from ayon_core.tools.common_models import ProjectsModel, HierarchyModel
|
||||
from ayon_core.tools.common_models import (
|
||||
ProjectsModel,
|
||||
HierarchyModel,
|
||||
UsersModel,
|
||||
)
|
||||
|
||||
from .abstract import (
|
||||
AbstractLauncherFrontEnd,
|
||||
|
|
@ -30,13 +34,12 @@ class BaseLauncherController(
|
|||
|
||||
self._addons_manager = None
|
||||
|
||||
self._username = NOT_SET
|
||||
|
||||
self._selection_model = LauncherSelectionModel(self)
|
||||
self._projects_model = ProjectsModel(self)
|
||||
self._hierarchy_model = HierarchyModel(self)
|
||||
self._actions_model = ActionsModel(self)
|
||||
self._workfiles_model = WorkfilesModel(self)
|
||||
self._users_model = UsersModel(self)
|
||||
|
||||
@property
|
||||
def log(self):
|
||||
|
|
@ -209,6 +212,7 @@ class BaseLauncherController(
|
|||
|
||||
self._projects_model.reset()
|
||||
self._hierarchy_model.reset()
|
||||
self._users_model.reset()
|
||||
|
||||
self._actions_model.refresh()
|
||||
self._projects_model.refresh()
|
||||
|
|
@ -229,8 +233,10 @@ class BaseLauncherController(
|
|||
|
||||
self._emit_event("controller.refresh.actions.finished")
|
||||
|
||||
def get_my_tasks_entity_ids(self, project_name: str):
|
||||
username = self._get_my_username()
|
||||
def get_my_tasks_entity_ids(
|
||||
self, project_name: str
|
||||
) -> dict[str, list[str]]:
|
||||
username = self._users_model.get_current_username()
|
||||
assignees = []
|
||||
if username:
|
||||
assignees.append(username)
|
||||
|
|
@ -238,10 +244,5 @@ class BaseLauncherController(
|
|||
project_name, assignees
|
||||
)
|
||||
|
||||
def _get_my_username(self):
|
||||
if self._username is NOT_SET:
|
||||
self._username = get_ayon_username()
|
||||
return self._username
|
||||
|
||||
def _emit_event(self, topic, data=None):
|
||||
self.emit_event(topic, data, "controller")
|
||||
|
|
|
|||
|
|
@ -2,19 +2,47 @@ import qtawesome
|
|||
from qtpy import QtWidgets, QtCore
|
||||
|
||||
from ayon_core.tools.utils import (
|
||||
PlaceholderLineEdit,
|
||||
SquareButton,
|
||||
RefreshButton,
|
||||
ProjectsCombobox,
|
||||
FoldersWidget,
|
||||
TasksWidget,
|
||||
NiceCheckbox,
|
||||
)
|
||||
from ayon_core.tools.utils.lib import checkstate_int_to_enum
|
||||
from ayon_core.tools.utils.folders_widget import FoldersFiltersWidget
|
||||
|
||||
from .workfiles_page import WorkfilesPage
|
||||
|
||||
|
||||
class LauncherFoldersWidget(FoldersWidget):
|
||||
focused_in = QtCore.Signal()
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self._folders_view.installEventFilter(self)
|
||||
|
||||
def eventFilter(self, obj, event):
|
||||
if event.type() == QtCore.QEvent.FocusIn:
|
||||
self.focused_in.emit()
|
||||
return False
|
||||
|
||||
|
||||
class LauncherTasksWidget(TasksWidget):
|
||||
focused_in = QtCore.Signal()
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self._tasks_view.installEventFilter(self)
|
||||
|
||||
def deselect(self):
|
||||
sel_model = self._tasks_view.selectionModel()
|
||||
sel_model.clearSelection()
|
||||
|
||||
def eventFilter(self, obj, event):
|
||||
if event.type() == QtCore.QEvent.FocusIn:
|
||||
self.focused_in.emit()
|
||||
return False
|
||||
|
||||
|
||||
class HierarchyPage(QtWidgets.QWidget):
|
||||
def __init__(self, controller, parent):
|
||||
super().__init__(parent)
|
||||
|
|
@ -46,34 +74,15 @@ class HierarchyPage(QtWidgets.QWidget):
|
|||
content_body.setOrientation(QtCore.Qt.Horizontal)
|
||||
|
||||
# - filters
|
||||
filters_widget = QtWidgets.QWidget(self)
|
||||
|
||||
folders_filter_text = PlaceholderLineEdit(filters_widget)
|
||||
folders_filter_text.setPlaceholderText("Filter folders...")
|
||||
|
||||
my_tasks_tooltip = (
|
||||
"Filter folders and task to only those you are assigned to."
|
||||
)
|
||||
my_tasks_label = QtWidgets.QLabel("My tasks", filters_widget)
|
||||
my_tasks_label.setToolTip(my_tasks_tooltip)
|
||||
|
||||
my_tasks_checkbox = NiceCheckbox(filters_widget)
|
||||
my_tasks_checkbox.setChecked(False)
|
||||
my_tasks_checkbox.setToolTip(my_tasks_tooltip)
|
||||
|
||||
filters_layout = QtWidgets.QHBoxLayout(filters_widget)
|
||||
filters_layout.setContentsMargins(0, 0, 0, 0)
|
||||
filters_layout.addWidget(folders_filter_text, 1)
|
||||
filters_layout.addWidget(my_tasks_label, 0)
|
||||
filters_layout.addWidget(my_tasks_checkbox, 0)
|
||||
filters_widget = FoldersFiltersWidget(self)
|
||||
|
||||
# - Folders widget
|
||||
folders_widget = FoldersWidget(controller, content_body)
|
||||
folders_widget = LauncherFoldersWidget(controller, content_body)
|
||||
folders_widget.set_header_visible(True)
|
||||
folders_widget.set_deselectable(True)
|
||||
|
||||
# - Tasks widget
|
||||
tasks_widget = TasksWidget(controller, content_body)
|
||||
tasks_widget = LauncherTasksWidget(controller, content_body)
|
||||
|
||||
# - Third page - Workfiles
|
||||
workfiles_page = WorkfilesPage(controller, content_body)
|
||||
|
|
@ -93,17 +102,18 @@ class HierarchyPage(QtWidgets.QWidget):
|
|||
|
||||
btn_back.clicked.connect(self._on_back_clicked)
|
||||
refresh_btn.clicked.connect(self._on_refresh_clicked)
|
||||
folders_filter_text.textChanged.connect(self._on_filter_text_changed)
|
||||
my_tasks_checkbox.stateChanged.connect(
|
||||
filters_widget.text_changed.connect(self._on_filter_text_changed)
|
||||
filters_widget.my_tasks_changed.connect(
|
||||
self._on_my_tasks_checkbox_state_changed
|
||||
)
|
||||
folders_widget.focused_in.connect(self._on_folders_focus)
|
||||
tasks_widget.focused_in.connect(self._on_tasks_focus)
|
||||
|
||||
self._is_visible = False
|
||||
self._controller = controller
|
||||
|
||||
self._btn_back = btn_back
|
||||
self._projects_combobox = projects_combobox
|
||||
self._my_tasks_checkbox = my_tasks_checkbox
|
||||
self._folders_widget = folders_widget
|
||||
self._tasks_widget = tasks_widget
|
||||
self._workfiles_page = workfiles_page
|
||||
|
|
@ -126,9 +136,6 @@ class HierarchyPage(QtWidgets.QWidget):
|
|||
self._folders_widget.refresh()
|
||||
self._tasks_widget.refresh()
|
||||
self._workfiles_page.refresh()
|
||||
self._on_my_tasks_checkbox_state_changed(
|
||||
self._my_tasks_checkbox.checkState()
|
||||
)
|
||||
|
||||
def _on_back_clicked(self):
|
||||
self._controller.set_selected_project(None)
|
||||
|
|
@ -139,11 +146,10 @@ class HierarchyPage(QtWidgets.QWidget):
|
|||
def _on_filter_text_changed(self, text):
|
||||
self._folders_widget.set_name_filter(text)
|
||||
|
||||
def _on_my_tasks_checkbox_state_changed(self, state):
|
||||
def _on_my_tasks_checkbox_state_changed(self, enabled: bool) -> None:
|
||||
folder_ids = None
|
||||
task_ids = None
|
||||
state = checkstate_int_to_enum(state)
|
||||
if state == QtCore.Qt.Checked:
|
||||
if enabled:
|
||||
entity_ids = self._controller.get_my_tasks_entity_ids(
|
||||
self._project_name
|
||||
)
|
||||
|
|
@ -151,3 +157,9 @@ class HierarchyPage(QtWidgets.QWidget):
|
|||
task_ids = entity_ids["task_ids"]
|
||||
self._folders_widget.set_folder_ids_filter(folder_ids)
|
||||
self._tasks_widget.set_task_ids_filter(task_ids)
|
||||
|
||||
def _on_folders_focus(self):
|
||||
self._workfiles_page.deselect()
|
||||
|
||||
def _on_tasks_focus(self):
|
||||
self._workfiles_page.deselect()
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ from typing import Optional
|
|||
import ayon_api
|
||||
from qtpy import QtCore, QtWidgets, QtGui
|
||||
|
||||
from ayon_core.tools.utils import get_qt_icon
|
||||
from ayon_core.tools.utils import get_qt_icon, DeselectableTreeView
|
||||
from ayon_core.tools.launcher.abstract import AbstractLauncherFrontEnd
|
||||
|
||||
VERSION_ROLE = QtCore.Qt.UserRole + 1
|
||||
|
|
@ -127,7 +127,7 @@ class WorkfilesModel(QtGui.QStandardItemModel):
|
|||
return icon
|
||||
|
||||
|
||||
class WorkfilesView(QtWidgets.QTreeView):
|
||||
class WorkfilesView(DeselectableTreeView):
|
||||
def drawBranches(self, painter, rect, index):
|
||||
return
|
||||
|
||||
|
|
@ -165,6 +165,10 @@ class WorkfilesPage(QtWidgets.QWidget):
|
|||
def refresh(self) -> None:
|
||||
self._workfiles_model.refresh()
|
||||
|
||||
def deselect(self):
|
||||
sel_model = self._workfiles_view.selectionModel()
|
||||
sel_model.clearSelection()
|
||||
|
||||
def _on_refresh(self) -> None:
|
||||
self._workfiles_proxy.sort(0, QtCore.Qt.DescendingOrder)
|
||||
|
||||
|
|
|
|||
|
|
@ -666,6 +666,21 @@ class FrontendLoaderController(_BaseLoaderController):
|
|||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_my_tasks_entity_ids(
|
||||
self, project_name: str
|
||||
) -> dict[str, list[str]]:
|
||||
"""Get entity ids for my tasks.
|
||||
|
||||
Args:
|
||||
project_name (str): Project name.
|
||||
|
||||
Returns:
|
||||
dict[str, list[str]]: Folder and task ids.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_available_tags_by_entity_type(
|
||||
self, project_name: str
|
||||
|
|
|
|||
|
|
@ -8,7 +8,11 @@ import ayon_api
|
|||
|
||||
from ayon_core.settings import get_project_settings
|
||||
from ayon_core.pipeline import get_current_host_name
|
||||
from ayon_core.lib import NestedCacheItem, CacheItem, filter_profiles
|
||||
from ayon_core.lib import (
|
||||
NestedCacheItem,
|
||||
CacheItem,
|
||||
filter_profiles,
|
||||
)
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.pipeline import Anatomy, get_current_context
|
||||
from ayon_core.host import ILoadHost
|
||||
|
|
@ -18,6 +22,7 @@ from ayon_core.tools.common_models import (
|
|||
ThumbnailsModel,
|
||||
TagItem,
|
||||
ProductTypeIconMapping,
|
||||
UsersModel,
|
||||
)
|
||||
|
||||
from .abstract import (
|
||||
|
|
@ -32,6 +37,8 @@ from .models import (
|
|||
SiteSyncModel
|
||||
)
|
||||
|
||||
NOT_SET = object()
|
||||
|
||||
|
||||
class ExpectedSelection:
|
||||
def __init__(self, controller):
|
||||
|
|
@ -124,6 +131,7 @@ class LoaderController(BackendLoaderController, FrontendLoaderController):
|
|||
self._loader_actions_model = LoaderActionsModel(self)
|
||||
self._thumbnails_model = ThumbnailsModel()
|
||||
self._sitesync_model = SiteSyncModel(self)
|
||||
self._users_model = UsersModel(self)
|
||||
|
||||
@property
|
||||
def log(self):
|
||||
|
|
@ -160,6 +168,7 @@ class LoaderController(BackendLoaderController, FrontendLoaderController):
|
|||
self._projects_model.reset()
|
||||
self._thumbnails_model.reset()
|
||||
self._sitesync_model.reset()
|
||||
self._users_model.reset()
|
||||
|
||||
self._projects_model.refresh()
|
||||
|
||||
|
|
@ -235,6 +244,17 @@ class LoaderController(BackendLoaderController, FrontendLoaderController):
|
|||
output[folder_id] = label
|
||||
return output
|
||||
|
||||
def get_my_tasks_entity_ids(
|
||||
self, project_name: str
|
||||
) -> dict[str, list[str]]:
|
||||
username = self._users_model.get_current_username()
|
||||
assignees = []
|
||||
if username:
|
||||
assignees.append(username)
|
||||
return self._hierarchy_model.get_entity_ids_for_assignees(
|
||||
project_name, assignees
|
||||
)
|
||||
|
||||
def get_available_tags_by_entity_type(
|
||||
self, project_name: str
|
||||
) -> dict[str, list[str]]:
|
||||
|
|
@ -476,20 +496,6 @@ class LoaderController(BackendLoaderController, FrontendLoaderController):
|
|||
def is_standard_projects_filter_enabled(self):
|
||||
return self._host is not None
|
||||
|
||||
def _get_project_anatomy(self, project_name):
|
||||
if not project_name:
|
||||
return None
|
||||
cache = self._project_anatomy_cache[project_name]
|
||||
if not cache.is_valid:
|
||||
cache.update_data(Anatomy(project_name))
|
||||
return cache.get_data()
|
||||
|
||||
def _create_event_system(self):
|
||||
return QueuedEventSystem()
|
||||
|
||||
def _emit_event(self, topic, data=None):
|
||||
self._event_system.emit(topic, data or {}, "controller")
|
||||
|
||||
def get_product_types_filter(self):
|
||||
output = ProductTypesFilter(
|
||||
is_allow_list=False,
|
||||
|
|
@ -545,3 +551,17 @@ class LoaderController(BackendLoaderController, FrontendLoaderController):
|
|||
product_types=profile["filter_product_types"]
|
||||
)
|
||||
return output
|
||||
|
||||
def _create_event_system(self):
|
||||
return QueuedEventSystem()
|
||||
|
||||
def _emit_event(self, topic, data=None):
|
||||
self._event_system.emit(topic, data or {}, "controller")
|
||||
|
||||
def _get_project_anatomy(self, project_name):
|
||||
if not project_name:
|
||||
return None
|
||||
cache = self._project_anatomy_cache[project_name]
|
||||
if not cache.is_valid:
|
||||
cache.update_data(Anatomy(project_name))
|
||||
return cache.get_data()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from typing import Optional
|
||||
|
||||
import qtpy
|
||||
from qtpy import QtWidgets, QtCore, QtGui
|
||||
|
||||
from ayon_core.tools.utils import (
|
||||
RecursiveSortFilterProxyModel,
|
||||
DeselectableTreeView,
|
||||
)
|
||||
from ayon_core.style import get_objected_colors
|
||||
from ayon_core.tools.utils import DeselectableTreeView
|
||||
from ayon_core.tools.utils.folders_widget import FoldersProxyModel
|
||||
|
||||
from ayon_core.tools.utils import (
|
||||
FoldersQtModel,
|
||||
|
|
@ -260,7 +260,7 @@ class LoaderFoldersWidget(QtWidgets.QWidget):
|
|||
QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
|
||||
folders_model = LoaderFoldersModel(controller)
|
||||
folders_proxy_model = RecursiveSortFilterProxyModel()
|
||||
folders_proxy_model = FoldersProxyModel()
|
||||
folders_proxy_model.setSourceModel(folders_model)
|
||||
folders_proxy_model.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
||||
|
||||
|
|
@ -314,6 +314,15 @@ class LoaderFoldersWidget(QtWidgets.QWidget):
|
|||
if name:
|
||||
self._folders_view.expandAll()
|
||||
|
||||
def set_folder_ids_filter(self, folder_ids: Optional[list[str]]):
|
||||
"""Set filter of folder ids.
|
||||
|
||||
Args:
|
||||
folder_ids (list[str]): The list of folder ids.
|
||||
|
||||
"""
|
||||
self._folders_proxy_model.set_folder_ids_filter(folder_ids)
|
||||
|
||||
def set_merged_products_selection(self, items):
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import collections
|
||||
import hashlib
|
||||
from typing import Optional
|
||||
|
||||
from qtpy import QtWidgets, QtCore, QtGui
|
||||
|
||||
from ayon_core.style import get_default_entity_icon_color
|
||||
from ayon_core.tools.utils import (
|
||||
RecursiveSortFilterProxyModel,
|
||||
DeselectableTreeView,
|
||||
TasksQtModel,
|
||||
TASKS_MODEL_SENDER_NAME,
|
||||
|
|
@ -15,9 +15,11 @@ from ayon_core.tools.utils.tasks_widget import (
|
|||
ITEM_NAME_ROLE,
|
||||
PARENT_ID_ROLE,
|
||||
TASK_TYPE_ROLE,
|
||||
TasksProxyModel,
|
||||
)
|
||||
from ayon_core.tools.utils.lib import RefreshThread, get_qt_icon
|
||||
|
||||
|
||||
# Role that can't clash with default 'tasks_widget' roles
|
||||
FOLDER_LABEL_ROLE = QtCore.Qt.UserRole + 100
|
||||
NO_TASKS_ID = "--no-task--"
|
||||
|
|
@ -295,7 +297,7 @@ class LoaderTasksQtModel(TasksQtModel):
|
|||
return super().data(index, role)
|
||||
|
||||
|
||||
class LoaderTasksProxyModel(RecursiveSortFilterProxyModel):
|
||||
class LoaderTasksProxyModel(TasksProxyModel):
|
||||
def lessThan(self, left, right):
|
||||
if left.data(ITEM_ID_ROLE) == NO_TASKS_ID:
|
||||
return False
|
||||
|
|
@ -303,6 +305,12 @@ class LoaderTasksProxyModel(RecursiveSortFilterProxyModel):
|
|||
return True
|
||||
return super().lessThan(left, right)
|
||||
|
||||
def filterAcceptsRow(self, row, parent_index):
|
||||
source_index = self.sourceModel().index(row, 0, parent_index)
|
||||
if source_index.data(ITEM_ID_ROLE) == NO_TASKS_ID:
|
||||
return True
|
||||
return super().filterAcceptsRow(row, parent_index)
|
||||
|
||||
|
||||
class LoaderTasksWidget(QtWidgets.QWidget):
|
||||
refreshed = QtCore.Signal()
|
||||
|
|
@ -363,6 +371,15 @@ class LoaderTasksWidget(QtWidgets.QWidget):
|
|||
if name:
|
||||
self._tasks_view.expandAll()
|
||||
|
||||
def set_task_ids_filter(self, task_ids: Optional[list[str]]):
|
||||
"""Set filter of folder ids.
|
||||
|
||||
Args:
|
||||
task_ids (list[str]): The list of folder ids.
|
||||
|
||||
"""
|
||||
self._tasks_proxy_model.set_task_ids_filter(task_ids)
|
||||
|
||||
def refresh(self):
|
||||
self._tasks_model.refresh()
|
||||
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ from qtpy import QtWidgets, QtCore, QtGui
|
|||
from ayon_core.resources import get_ayon_icon_filepath
|
||||
from ayon_core.style import load_stylesheet
|
||||
from ayon_core.tools.utils import (
|
||||
PlaceholderLineEdit,
|
||||
ErrorMessageBox,
|
||||
ThumbnailPainterWidget,
|
||||
RefreshButton,
|
||||
GoToCurrentButton,
|
||||
FoldersFiltersWidget,
|
||||
)
|
||||
from ayon_core.tools.utils.lib import center_window
|
||||
from ayon_core.tools.utils import ProjectsCombobox
|
||||
|
|
@ -170,15 +170,14 @@ class LoaderWindow(QtWidgets.QWidget):
|
|||
context_top_layout.addWidget(go_to_current_btn, 0)
|
||||
context_top_layout.addWidget(refresh_btn, 0)
|
||||
|
||||
folders_filter_input = PlaceholderLineEdit(context_widget)
|
||||
folders_filter_input.setPlaceholderText("Folder name filter...")
|
||||
filters_widget = FoldersFiltersWidget(context_widget)
|
||||
|
||||
folders_widget = LoaderFoldersWidget(controller, context_widget)
|
||||
|
||||
context_layout = QtWidgets.QVBoxLayout(context_widget)
|
||||
context_layout.setContentsMargins(0, 0, 0, 0)
|
||||
context_layout.addWidget(context_top_widget, 0)
|
||||
context_layout.addWidget(folders_filter_input, 0)
|
||||
context_layout.addWidget(filters_widget, 0)
|
||||
context_layout.addWidget(folders_widget, 1)
|
||||
|
||||
tasks_widget = LoaderTasksWidget(controller, context_widget)
|
||||
|
|
@ -247,9 +246,12 @@ class LoaderWindow(QtWidgets.QWidget):
|
|||
projects_combobox.refreshed.connect(self._on_projects_refresh)
|
||||
folders_widget.refreshed.connect(self._on_folders_refresh)
|
||||
products_widget.refreshed.connect(self._on_products_refresh)
|
||||
folders_filter_input.textChanged.connect(
|
||||
filters_widget.text_changed.connect(
|
||||
self._on_folder_filter_change
|
||||
)
|
||||
filters_widget.my_tasks_changed.connect(
|
||||
self._on_my_tasks_checkbox_state_changed
|
||||
)
|
||||
search_bar.filter_changed.connect(self._on_filter_change)
|
||||
product_group_checkbox.stateChanged.connect(
|
||||
self._on_product_group_change
|
||||
|
|
@ -303,7 +305,7 @@ class LoaderWindow(QtWidgets.QWidget):
|
|||
self._refresh_btn = refresh_btn
|
||||
self._projects_combobox = projects_combobox
|
||||
|
||||
self._folders_filter_input = folders_filter_input
|
||||
self._filters_widget = filters_widget
|
||||
self._folders_widget = folders_widget
|
||||
|
||||
self._tasks_widget = tasks_widget
|
||||
|
|
@ -421,9 +423,21 @@ class LoaderWindow(QtWidgets.QWidget):
|
|||
self._group_dialog.set_product_ids(project_name, product_ids)
|
||||
self._group_dialog.show()
|
||||
|
||||
def _on_folder_filter_change(self, text):
|
||||
def _on_folder_filter_change(self, text: str) -> None:
|
||||
self._folders_widget.set_name_filter(text)
|
||||
|
||||
def _on_my_tasks_checkbox_state_changed(self, enabled: bool) -> None:
|
||||
folder_ids = None
|
||||
task_ids = None
|
||||
if enabled:
|
||||
entity_ids = self._controller.get_my_tasks_entity_ids(
|
||||
self._selected_project_name
|
||||
)
|
||||
folder_ids = entity_ids["folder_ids"]
|
||||
task_ids = entity_ids["task_ids"]
|
||||
self._folders_widget.set_folder_ids_filter(folder_ids)
|
||||
self._tasks_widget.set_task_ids_filter(task_ids)
|
||||
|
||||
def _on_product_group_change(self):
|
||||
self._products_widget.set_enable_grouping(
|
||||
self._product_group_checkbox.isChecked()
|
||||
|
|
|
|||
|
|
@ -295,6 +295,21 @@ class AbstractPublisherFrontend(AbstractPublisherCommon):
|
|||
"""Get folder id from folder path."""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_my_tasks_entity_ids(
|
||||
self, project_name: str
|
||||
) -> dict[str, list[str]]:
|
||||
"""Get entity ids for my tasks.
|
||||
|
||||
Args:
|
||||
project_name (str): Project name.
|
||||
|
||||
Returns:
|
||||
dict[str, list[str]]: Folder and task ids.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
# --- Create ---
|
||||
@abstractmethod
|
||||
def get_creator_items(self) -> Dict[str, "CreatorItem"]:
|
||||
|
|
|
|||
|
|
@ -11,7 +11,11 @@ from ayon_core.pipeline import (
|
|||
registered_host,
|
||||
get_process_id,
|
||||
)
|
||||
from ayon_core.tools.common_models import ProjectsModel, HierarchyModel
|
||||
from ayon_core.tools.common_models import (
|
||||
ProjectsModel,
|
||||
HierarchyModel,
|
||||
UsersModel,
|
||||
)
|
||||
|
||||
from .models import (
|
||||
PublishModel,
|
||||
|
|
@ -101,6 +105,7 @@ class PublisherController(
|
|||
# Cacher of avalon documents
|
||||
self._projects_model = ProjectsModel(self)
|
||||
self._hierarchy_model = HierarchyModel(self)
|
||||
self._users_model = UsersModel(self)
|
||||
|
||||
@property
|
||||
def log(self):
|
||||
|
|
@ -317,6 +322,17 @@ class PublisherController(
|
|||
return False
|
||||
return True
|
||||
|
||||
def get_my_tasks_entity_ids(
|
||||
self, project_name: str
|
||||
) -> dict[str, list[str]]:
|
||||
username = self._users_model.get_current_username()
|
||||
assignees = []
|
||||
if username:
|
||||
assignees.append(username)
|
||||
return self._hierarchy_model.get_entity_ids_for_assignees(
|
||||
project_name, assignees
|
||||
)
|
||||
|
||||
# --- Publish specific callbacks ---
|
||||
def get_context_title(self):
|
||||
"""Get context title for artist shown at the top of main window."""
|
||||
|
|
@ -359,6 +375,7 @@ class PublisherController(
|
|||
self._emit_event("controller.reset.started")
|
||||
|
||||
self._hierarchy_model.reset()
|
||||
self._users_model.reset()
|
||||
|
||||
# Publish part must be reset after plugins
|
||||
self._create_model.reset()
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ class ContextCardWidget(CardWidget):
|
|||
Is not visually under group widget and is always at the top of card view.
|
||||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent: QtWidgets.QWidget):
|
||||
super().__init__(parent)
|
||||
|
||||
self._id = CONTEXT_ID
|
||||
|
|
@ -211,7 +211,7 @@ class ContextCardWidget(CardWidget):
|
|||
icon_widget = PublishPixmapLabel(None, self)
|
||||
icon_widget.setObjectName("ProductTypeIconLabel")
|
||||
|
||||
label_widget = QtWidgets.QLabel(CONTEXT_LABEL, self)
|
||||
label_widget = QtWidgets.QLabel(f"<span>{CONTEXT_LABEL}</span>", self)
|
||||
|
||||
icon_layout = QtWidgets.QHBoxLayout()
|
||||
icon_layout.setContentsMargins(5, 5, 5, 5)
|
||||
|
|
@ -288,6 +288,8 @@ class InstanceCardWidget(CardWidget):
|
|||
self._last_product_name = None
|
||||
self._last_variant = None
|
||||
self._last_label = None
|
||||
self._last_folder_path = None
|
||||
self._last_task_name = None
|
||||
|
||||
icon_widget = IconValuePixmapLabel(group_icon, self)
|
||||
icon_widget.setObjectName("ProductTypeIconLabel")
|
||||
|
|
@ -383,29 +385,54 @@ class InstanceCardWidget(CardWidget):
|
|||
self._icon_widget.setVisible(valid)
|
||||
self._context_warning.setVisible(not valid)
|
||||
|
||||
@staticmethod
|
||||
def _get_card_widget_sub_label(
|
||||
folder_path: Optional[str],
|
||||
task_name: Optional[str],
|
||||
) -> str:
|
||||
sublabel = ""
|
||||
if folder_path:
|
||||
folder_name = folder_path.rsplit("/", 1)[-1]
|
||||
sublabel = f"<b>{folder_name}</b>"
|
||||
if task_name:
|
||||
sublabel += f" - <i>{task_name}</i>"
|
||||
return sublabel
|
||||
|
||||
def _update_product_name(self):
|
||||
variant = self.instance.variant
|
||||
product_name = self.instance.product_name
|
||||
label = self.instance.label
|
||||
folder_path = self.instance.folder_path
|
||||
task_name = self.instance.task_name
|
||||
|
||||
if (
|
||||
variant == self._last_variant
|
||||
and product_name == self._last_product_name
|
||||
and label == self._last_label
|
||||
and folder_path == self._last_folder_path
|
||||
and task_name == self._last_task_name
|
||||
):
|
||||
return
|
||||
|
||||
self._last_variant = variant
|
||||
self._last_product_name = product_name
|
||||
self._last_label = label
|
||||
self._last_folder_path = folder_path
|
||||
self._last_task_name = task_name
|
||||
|
||||
# Make `variant` bold
|
||||
label = html_escape(self.instance.label)
|
||||
found_parts = set(re.findall(variant, label, re.IGNORECASE))
|
||||
if found_parts:
|
||||
for part in found_parts:
|
||||
replacement = "<b>{}</b>".format(part)
|
||||
replacement = f"<b>{part}</b>"
|
||||
label = label.replace(part, replacement)
|
||||
|
||||
label = f"<span>{label}</span>"
|
||||
sublabel = self._get_card_widget_sub_label(folder_path, task_name)
|
||||
if sublabel:
|
||||
label += f"<br/><span style=\"font-size: 8pt;\">{sublabel}</span>"
|
||||
|
||||
self._label_widget.setText(label)
|
||||
# HTML text will cause that label start catch mouse clicks
|
||||
# - disabling with changing interaction flag
|
||||
|
|
@ -702,11 +729,9 @@ class InstanceCardView(AbstractInstanceView):
|
|||
|
||||
def refresh(self):
|
||||
"""Refresh instances in view based on CreatedContext."""
|
||||
|
||||
self._make_sure_context_widget_exists()
|
||||
|
||||
self._update_convertors_group()
|
||||
|
||||
context_info_by_id = self._controller.get_instances_context_info()
|
||||
|
||||
# Prepare instances by group and identifiers by group
|
||||
|
|
@ -814,6 +839,8 @@ class InstanceCardView(AbstractInstanceView):
|
|||
widget.setVisible(False)
|
||||
widget.deleteLater()
|
||||
|
||||
sorted_group_names.insert(0, CONTEXT_GROUP)
|
||||
|
||||
self._parent_id_by_id = parent_id_by_id
|
||||
self._instance_ids_by_parent_id = instance_ids_by_parent_id
|
||||
self._group_name_by_instance_id = group_by_instance_id
|
||||
|
|
@ -881,7 +908,7 @@ class InstanceCardView(AbstractInstanceView):
|
|||
context_info,
|
||||
is_parent_active,
|
||||
group_icon,
|
||||
group_widget
|
||||
group_widget,
|
||||
)
|
||||
widget.selected.connect(self._on_widget_selection)
|
||||
widget.active_changed.connect(self._on_active_changed)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
from qtpy import QtWidgets, QtCore
|
||||
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.tools.utils import PlaceholderLineEdit, GoToCurrentButton
|
||||
|
||||
from ayon_core.tools.common_models import HierarchyExpectedSelection
|
||||
from ayon_core.tools.utils import FoldersWidget, TasksWidget
|
||||
from ayon_core.tools.utils import (
|
||||
FoldersWidget,
|
||||
TasksWidget,
|
||||
FoldersFiltersWidget,
|
||||
GoToCurrentButton,
|
||||
)
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
|
||||
|
||||
|
|
@ -180,8 +184,7 @@ class CreateContextWidget(QtWidgets.QWidget):
|
|||
|
||||
headers_widget = QtWidgets.QWidget(self)
|
||||
|
||||
folder_filter_input = PlaceholderLineEdit(headers_widget)
|
||||
folder_filter_input.setPlaceholderText("Filter folders..")
|
||||
filters_widget = FoldersFiltersWidget(headers_widget)
|
||||
|
||||
current_context_btn = GoToCurrentButton(headers_widget)
|
||||
current_context_btn.setToolTip("Go to current context")
|
||||
|
|
@ -189,7 +192,8 @@ class CreateContextWidget(QtWidgets.QWidget):
|
|||
|
||||
headers_layout = QtWidgets.QHBoxLayout(headers_widget)
|
||||
headers_layout.setContentsMargins(0, 0, 0, 0)
|
||||
headers_layout.addWidget(folder_filter_input, 1)
|
||||
headers_layout.setSpacing(5)
|
||||
headers_layout.addWidget(filters_widget, 1)
|
||||
headers_layout.addWidget(current_context_btn, 0)
|
||||
|
||||
hierarchy_controller = CreateHierarchyController(controller)
|
||||
|
|
@ -207,15 +211,16 @@ class CreateContextWidget(QtWidgets.QWidget):
|
|||
main_layout.setContentsMargins(0, 0, 0, 0)
|
||||
main_layout.setSpacing(0)
|
||||
main_layout.addWidget(headers_widget, 0)
|
||||
main_layout.addSpacing(5)
|
||||
main_layout.addWidget(folders_widget, 2)
|
||||
main_layout.addWidget(tasks_widget, 1)
|
||||
|
||||
folders_widget.selection_changed.connect(self._on_folder_change)
|
||||
tasks_widget.selection_changed.connect(self._on_task_change)
|
||||
current_context_btn.clicked.connect(self._on_current_context_click)
|
||||
folder_filter_input.textChanged.connect(self._on_folder_filter_change)
|
||||
filters_widget.text_changed.connect(self._on_folder_filter_change)
|
||||
filters_widget.my_tasks_changed.connect(self._on_my_tasks_change)
|
||||
|
||||
self._folder_filter_input = folder_filter_input
|
||||
self._current_context_btn = current_context_btn
|
||||
self._folders_widget = folders_widget
|
||||
self._tasks_widget = tasks_widget
|
||||
|
|
@ -303,5 +308,17 @@ class CreateContextWidget(QtWidgets.QWidget):
|
|||
self._last_project_name, folder_id, task_name
|
||||
)
|
||||
|
||||
def _on_folder_filter_change(self, text):
|
||||
def _on_folder_filter_change(self, text: str) -> None:
|
||||
self._folders_widget.set_name_filter(text)
|
||||
|
||||
def _on_my_tasks_change(self, enabled: bool) -> None:
|
||||
folder_ids = None
|
||||
task_ids = None
|
||||
if enabled:
|
||||
entity_ids = self._controller.get_my_tasks_entity_ids(
|
||||
self._last_project_name
|
||||
)
|
||||
folder_ids = entity_ids["folder_ids"]
|
||||
task_ids = entity_ids["task_ids"]
|
||||
self._folders_widget.set_folder_ids_filter(folder_ids)
|
||||
self._tasks_widget.set_task_ids_filter(task_ids)
|
||||
|
|
|
|||
|
|
@ -710,11 +710,13 @@ class CreateWidget(QtWidgets.QWidget):
|
|||
|
||||
def _on_first_show(self):
|
||||
width = self.width()
|
||||
part = int(width / 4)
|
||||
rem_width = width - part
|
||||
self._main_splitter_widget.setSizes([part, rem_width])
|
||||
rem_width = rem_width - part
|
||||
self._creators_splitter.setSizes([part, rem_width])
|
||||
part = int(width / 9)
|
||||
context_width = part * 3
|
||||
create_sel_width = part * 2
|
||||
rem_width = width - context_width
|
||||
self._main_splitter_widget.setSizes([context_width, rem_width])
|
||||
rem_width -= create_sel_width
|
||||
self._creators_splitter.setSizes([create_sel_width, rem_width])
|
||||
|
||||
def showEvent(self, event):
|
||||
super().showEvent(event)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
from qtpy import QtWidgets
|
||||
|
||||
from ayon_core.lib.events import QueuedEventSystem
|
||||
from ayon_core.tools.utils import PlaceholderLineEdit, FoldersWidget
|
||||
from ayon_core.tools.utils import (
|
||||
FoldersWidget,
|
||||
FoldersFiltersWidget,
|
||||
)
|
||||
from ayon_core.tools.publisher.abstract import AbstractPublisherFrontend
|
||||
|
||||
|
||||
|
|
@ -43,8 +46,7 @@ class FoldersDialog(QtWidgets.QDialog):
|
|||
super().__init__(parent)
|
||||
self.setWindowTitle("Select folder")
|
||||
|
||||
filter_input = PlaceholderLineEdit(self)
|
||||
filter_input.setPlaceholderText("Filter folders..")
|
||||
filters_widget = FoldersFiltersWidget(self)
|
||||
|
||||
folders_controller = FoldersDialogController(controller)
|
||||
folders_widget = FoldersWidget(folders_controller, self)
|
||||
|
|
@ -59,7 +61,8 @@ class FoldersDialog(QtWidgets.QDialog):
|
|||
btns_layout.addWidget(cancel_btn)
|
||||
|
||||
layout = QtWidgets.QVBoxLayout(self)
|
||||
layout.addWidget(filter_input, 0)
|
||||
layout.setSpacing(5)
|
||||
layout.addWidget(filters_widget, 0)
|
||||
layout.addWidget(folders_widget, 1)
|
||||
layout.addLayout(btns_layout, 0)
|
||||
|
||||
|
|
@ -68,12 +71,13 @@ class FoldersDialog(QtWidgets.QDialog):
|
|||
)
|
||||
|
||||
folders_widget.double_clicked.connect(self._on_ok_clicked)
|
||||
filter_input.textChanged.connect(self._on_filter_change)
|
||||
filters_widget.text_changed.connect(self._on_filter_change)
|
||||
filters_widget.my_tasks_changed.connect(self._on_my_tasks_change)
|
||||
ok_btn.clicked.connect(self._on_ok_clicked)
|
||||
cancel_btn.clicked.connect(self._on_cancel_clicked)
|
||||
|
||||
self._controller = controller
|
||||
self._filter_input = filter_input
|
||||
self._filters_widget = filters_widget
|
||||
self._ok_btn = ok_btn
|
||||
self._cancel_btn = cancel_btn
|
||||
|
||||
|
|
@ -88,6 +92,49 @@ class FoldersDialog(QtWidgets.QDialog):
|
|||
self._first_show = True
|
||||
self._default_height = 500
|
||||
|
||||
self._project_name = None
|
||||
|
||||
def showEvent(self, event):
|
||||
"""Refresh folders widget on show."""
|
||||
super().showEvent(event)
|
||||
if self._first_show:
|
||||
self._first_show = False
|
||||
self._on_first_show()
|
||||
# Refresh on show
|
||||
self.reset(False)
|
||||
|
||||
def reset(self, force=True):
|
||||
"""Reset widget."""
|
||||
if not force and not self._soft_reset_enabled:
|
||||
return
|
||||
|
||||
self._project_name = self._controller.get_current_project_name()
|
||||
if self._soft_reset_enabled:
|
||||
self._soft_reset_enabled = False
|
||||
|
||||
self._folders_widget.set_project_name(self._project_name)
|
||||
|
||||
def get_selected_folder_path(self):
|
||||
"""Get selected folder path."""
|
||||
return self._selected_folder_path
|
||||
|
||||
def set_selected_folders(self, folder_paths: list[str]) -> None:
|
||||
"""Change preselected folder before showing the dialog.
|
||||
|
||||
This also resets model and clean filter.
|
||||
"""
|
||||
self.reset(False)
|
||||
self._filters_widget.set_text("")
|
||||
self._filters_widget.set_my_tasks_checked(False)
|
||||
|
||||
folder_id = None
|
||||
for folder_path in folder_paths:
|
||||
folder_id = self._controller.get_folder_id_from_path(folder_path)
|
||||
if folder_id:
|
||||
break
|
||||
if folder_id:
|
||||
self._folders_widget.set_selected_folder(folder_id)
|
||||
|
||||
def _on_first_show(self):
|
||||
center = self.rect().center()
|
||||
size = self.size()
|
||||
|
|
@ -103,27 +150,6 @@ class FoldersDialog(QtWidgets.QDialog):
|
|||
# Change reset enabled so model is reset on show event
|
||||
self._soft_reset_enabled = True
|
||||
|
||||
def showEvent(self, event):
|
||||
"""Refresh folders widget on show."""
|
||||
super().showEvent(event)
|
||||
if self._first_show:
|
||||
self._first_show = False
|
||||
self._on_first_show()
|
||||
# Refresh on show
|
||||
self.reset(False)
|
||||
|
||||
def reset(self, force=True):
|
||||
"""Reset widget."""
|
||||
if not force and not self._soft_reset_enabled:
|
||||
return
|
||||
|
||||
if self._soft_reset_enabled:
|
||||
self._soft_reset_enabled = False
|
||||
|
||||
self._folders_widget.set_project_name(
|
||||
self._controller.get_current_project_name()
|
||||
)
|
||||
|
||||
def _on_filter_change(self, text):
|
||||
"""Trigger change of filter of folders."""
|
||||
self._folders_widget.set_name_filter(text)
|
||||
|
|
@ -137,22 +163,11 @@ class FoldersDialog(QtWidgets.QDialog):
|
|||
)
|
||||
self.done(1)
|
||||
|
||||
def set_selected_folders(self, folder_paths):
|
||||
"""Change preselected folder before showing the dialog.
|
||||
|
||||
This also resets model and clean filter.
|
||||
"""
|
||||
self.reset(False)
|
||||
self._filter_input.setText("")
|
||||
|
||||
folder_id = None
|
||||
for folder_path in folder_paths:
|
||||
folder_id = self._controller.get_folder_id_from_path(folder_path)
|
||||
if folder_id:
|
||||
break
|
||||
if folder_id:
|
||||
self._folders_widget.set_selected_folder(folder_id)
|
||||
|
||||
def get_selected_folder_path(self):
|
||||
"""Get selected folder path."""
|
||||
return self._selected_folder_path
|
||||
def _on_my_tasks_change(self, enabled: bool) -> None:
|
||||
folder_ids = None
|
||||
if enabled:
|
||||
entity_ids = self._controller.get_my_tasks_entity_ids(
|
||||
self._project_name
|
||||
)
|
||||
folder_ids = entity_ids["folder_ids"]
|
||||
self._folders_widget.set_folder_ids_filter(folder_ids)
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ from .folders_widget import (
|
|||
FoldersQtModel,
|
||||
FOLDERS_MODEL_SENDER_NAME,
|
||||
SimpleFoldersWidget,
|
||||
FoldersFiltersWidget,
|
||||
)
|
||||
|
||||
from .tasks_widget import (
|
||||
|
|
@ -160,6 +161,7 @@ __all__ = (
|
|||
"FoldersQtModel",
|
||||
"FOLDERS_MODEL_SENDER_NAME",
|
||||
"SimpleFoldersWidget",
|
||||
"FoldersFiltersWidget",
|
||||
|
||||
"TasksWidget",
|
||||
"TasksQtModel",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ from ayon_core.tools.common_models import (
|
|||
from .models import RecursiveSortFilterProxyModel
|
||||
from .views import TreeView
|
||||
from .lib import RefreshThread, get_qt_icon
|
||||
from .widgets import PlaceholderLineEdit
|
||||
from .nice_checkbox import NiceCheckbox
|
||||
|
||||
|
||||
FOLDERS_MODEL_SENDER_NAME = "qt_folders_model"
|
||||
|
|
@ -343,6 +345,8 @@ class FoldersProxyModel(RecursiveSortFilterProxyModel):
|
|||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
|
||||
|
||||
self._folder_ids_filter = None
|
||||
|
||||
def set_folder_ids_filter(self, folder_ids: Optional[list[str]]):
|
||||
|
|
@ -794,3 +798,47 @@ class SimpleFoldersWidget(FoldersWidget):
|
|||
event (Event): Triggered event.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class FoldersFiltersWidget(QtWidgets.QWidget):
|
||||
"""Helper widget for most commonly used filters in context selection."""
|
||||
text_changed = QtCore.Signal(str)
|
||||
my_tasks_changed = QtCore.Signal(bool)
|
||||
|
||||
def __init__(self, parent: QtWidgets.QWidget) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
folders_filter_input = PlaceholderLineEdit(self)
|
||||
folders_filter_input.setPlaceholderText("Folder name filter...")
|
||||
|
||||
my_tasks_tooltip = (
|
||||
"Filter folders and task to only those you are assigned to."
|
||||
)
|
||||
my_tasks_label = QtWidgets.QLabel("My tasks", self)
|
||||
my_tasks_label.setToolTip(my_tasks_tooltip)
|
||||
|
||||
my_tasks_checkbox = NiceCheckbox(self)
|
||||
my_tasks_checkbox.setChecked(False)
|
||||
my_tasks_checkbox.setToolTip(my_tasks_tooltip)
|
||||
|
||||
layout = QtWidgets.QHBoxLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(5)
|
||||
layout.addWidget(folders_filter_input, 1)
|
||||
layout.addWidget(my_tasks_label, 0)
|
||||
layout.addWidget(my_tasks_checkbox, 0)
|
||||
|
||||
folders_filter_input.textChanged.connect(self.text_changed)
|
||||
my_tasks_checkbox.stateChanged.connect(self._on_my_tasks_change)
|
||||
|
||||
self._folders_filter_input = folders_filter_input
|
||||
self._my_tasks_checkbox = my_tasks_checkbox
|
||||
|
||||
def set_text(self, text: str) -> None:
|
||||
self._folders_filter_input.setText(text)
|
||||
|
||||
def set_my_tasks_checked(self, checked: bool) -> None:
|
||||
self._my_tasks_checkbox.setChecked(checked)
|
||||
|
||||
def _on_my_tasks_change(self, _state: int) -> None:
|
||||
self.my_tasks_changed.emit(self._my_tasks_checkbox.isChecked())
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@ from ayon_core.tools.utils import (
|
|||
FoldersWidget,
|
||||
GoToCurrentButton,
|
||||
MessageOverlayObject,
|
||||
NiceCheckbox,
|
||||
PlaceholderLineEdit,
|
||||
RefreshButton,
|
||||
TasksWidget,
|
||||
FoldersFiltersWidget,
|
||||
)
|
||||
from ayon_core.tools.utils.lib import checkstate_int_to_enum
|
||||
from ayon_core.tools.workfiles.control import BaseWorkfileController
|
||||
|
||||
from .files_widget import FilesWidget
|
||||
|
|
@ -69,7 +68,6 @@ class WorkfilesToolWindow(QtWidgets.QWidget):
|
|||
self._default_window_flags = flags
|
||||
|
||||
self._folders_widget = None
|
||||
self._folder_filter_input = None
|
||||
|
||||
self._files_widget = None
|
||||
|
||||
|
|
@ -178,48 +176,33 @@ class WorkfilesToolWindow(QtWidgets.QWidget):
|
|||
col_widget = QtWidgets.QWidget(parent)
|
||||
header_widget = QtWidgets.QWidget(col_widget)
|
||||
|
||||
folder_filter_input = PlaceholderLineEdit(header_widget)
|
||||
folder_filter_input.setPlaceholderText("Filter folders..")
|
||||
filters_widget = FoldersFiltersWidget(header_widget)
|
||||
|
||||
go_to_current_btn = GoToCurrentButton(header_widget)
|
||||
refresh_btn = RefreshButton(header_widget)
|
||||
|
||||
header_layout = QtWidgets.QHBoxLayout(header_widget)
|
||||
header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
header_layout.addWidget(filters_widget, 1)
|
||||
header_layout.addWidget(go_to_current_btn, 0)
|
||||
header_layout.addWidget(refresh_btn, 0)
|
||||
|
||||
folder_widget = FoldersWidget(
|
||||
controller, col_widget, handle_expected_selection=True
|
||||
)
|
||||
|
||||
my_tasks_tooltip = (
|
||||
"Filter folders and task to only those you are assigned to."
|
||||
)
|
||||
|
||||
my_tasks_label = QtWidgets.QLabel("My tasks")
|
||||
my_tasks_label.setToolTip(my_tasks_tooltip)
|
||||
|
||||
my_tasks_checkbox = NiceCheckbox(folder_widget)
|
||||
my_tasks_checkbox.setChecked(False)
|
||||
my_tasks_checkbox.setToolTip(my_tasks_tooltip)
|
||||
|
||||
header_layout = QtWidgets.QHBoxLayout(header_widget)
|
||||
header_layout.setContentsMargins(0, 0, 0, 0)
|
||||
header_layout.addWidget(folder_filter_input, 1)
|
||||
header_layout.addWidget(go_to_current_btn, 0)
|
||||
header_layout.addWidget(refresh_btn, 0)
|
||||
header_layout.addWidget(my_tasks_label, 0)
|
||||
header_layout.addWidget(my_tasks_checkbox, 0)
|
||||
|
||||
col_layout = QtWidgets.QVBoxLayout(col_widget)
|
||||
col_layout.setContentsMargins(0, 0, 0, 0)
|
||||
col_layout.addWidget(header_widget, 0)
|
||||
col_layout.addWidget(folder_widget, 1)
|
||||
|
||||
folder_filter_input.textChanged.connect(self._on_folder_filter_change)
|
||||
go_to_current_btn.clicked.connect(self._on_go_to_current_clicked)
|
||||
refresh_btn.clicked.connect(self._on_refresh_clicked)
|
||||
my_tasks_checkbox.stateChanged.connect(
|
||||
filters_widget.text_changed.connect(self._on_folder_filter_change)
|
||||
filters_widget.my_tasks_changed.connect(
|
||||
self._on_my_tasks_checkbox_state_changed
|
||||
)
|
||||
go_to_current_btn.clicked.connect(self._on_go_to_current_clicked)
|
||||
refresh_btn.clicked.connect(self._on_refresh_clicked)
|
||||
|
||||
self._folder_filter_input = folder_filter_input
|
||||
self._folders_widget = folder_widget
|
||||
|
||||
return col_widget
|
||||
|
|
@ -403,11 +386,10 @@ class WorkfilesToolWindow(QtWidgets.QWidget):
|
|||
else:
|
||||
self.close()
|
||||
|
||||
def _on_my_tasks_checkbox_state_changed(self, state):
|
||||
def _on_my_tasks_checkbox_state_changed(self, enabled: bool) -> None:
|
||||
folder_ids = None
|
||||
task_ids = None
|
||||
state = checkstate_int_to_enum(state)
|
||||
if state == QtCore.Qt.Checked:
|
||||
if enabled:
|
||||
entity_ids = self._controller.get_my_tasks_entity_ids(
|
||||
self._project_name
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue