Merge pull request #137 from ynput/enhancement/traypublisher-using-ayon-projects-model

TrayPublisher: Use AYON projects model
This commit is contained in:
Jakub Trllo 2024-02-29 12:56:49 +01:00 committed by GitHub
commit d856bd0cb5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 49 additions and 188 deletions

View file

@ -3,6 +3,10 @@ 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 (
@ -28,6 +32,10 @@ __all__ = (
"ProjectsCombobox",
"ProjectsQtModel",
"ProjectSortFilterProxy",
"PROJECT_NAME_ROLE",
"PROJECT_IS_CURRENT_ROLE",
"PROJECT_IS_ACTIVE_ROLE",
"PROJECT_IS_LIBRARY_ROLE",
"FoldersWidget",
"FoldersQtModel",

View file

@ -47,6 +47,22 @@ class ProjectsQtModel(QtGui.QStandardItemModel):
def has_content(self):
return len(self._project_items) > 0
def get_index_by_project_name(self, project_name):
"""Get index of project by name.
Args:
project_name (str): Project name.
Returns:
QtCore.QModelIndex: Index of project item. Index is not valid
if project is not found.
"""
item = self._project_items.get(project_name)
if item is None:
return QtCore.QModelIndex()
return self.indexFromItem(item)
def set_select_item_visible(self, visible):
if self._select_item_visible is visible:
return

View file

@ -10,22 +10,31 @@ import platform
from qtpy import QtWidgets, QtCore
import qtawesome
import appdirs
from ayon_core.lib import JSONSettingRegistry, is_running_from_build
from ayon_core.lib import AYONSettingsRegistry, is_running_from_build
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.utils.constants import PROJECT_NAME_ROLE
from ayon_core.tools.utils.models import (
ProjectModel,
ProjectSortFilterProxy
from ayon_core.tools.ayon_utils.models import ProjectsModel
from ayon_core.tools.ayon_utils.widgets import (
ProjectsQtModel,
ProjectSortFilterProxy,
PROJECT_NAME_ROLE,
)
class TrayPublisherRegistry(AYONSettingsRegistry):
def __init__(self):
super(TrayPublisherRegistry, self).__init__("traypublisher")
class TrayPublisherController(QtPublisherController):
def __init__(self, *args, **kwargs):
super(TrayPublisherController, self).__init__(*args, **kwargs)
self._projects_model = ProjectsModel(self)
@property
def host(self):
return self._host
@ -34,28 +43,14 @@ class TrayPublisherController(QtPublisherController):
self._hierarchy_model.reset()
self._asset_docs_cache.reset()
class TrayPublisherRegistry(JSONSettingRegistry):
"""Class handling AYON general settings registry.
Attributes:
vendor (str): Name used for path construction.
product (str): Additional name used for path construction.
"""
def __init__(self):
self.vendor = "pypeclub"
self.product = "openpype"
name = "tray_publisher"
path = appdirs.user_data_dir(self.product, self.vendor)
super(TrayPublisherRegistry, self).__init__(name, path)
def get_project_items(self, sender=None):
return self._projects_model.get_project_items(sender)
class StandaloneOverlayWidget(QtWidgets.QFrame):
project_selected = QtCore.Signal(str)
def __init__(self, publisher_window):
def __init__(self, controller, publisher_window):
super(StandaloneOverlayWidget, self).__init__(publisher_window)
self.setObjectName("OverlayFrame")
@ -67,7 +62,7 @@ class StandaloneOverlayWidget(QtWidgets.QFrame):
header_label = QtWidgets.QLabel("Choose project", content_widget)
header_label.setObjectName("ChooseProjectLabel")
# Create project models and view
projects_model = ProjectModel()
projects_model = ProjectsQtModel(controller)
projects_proxy = ProjectSortFilterProxy()
projects_proxy.setSourceModel(projects_model)
projects_proxy.setFilterKeyColumn(0)
@ -138,12 +133,11 @@ class StandaloneOverlayWidget(QtWidgets.QFrame):
project_name = None
if project_name:
index = None
src_index = self._projects_model.find_project(project_name)
if src_index is not None:
index = self._projects_proxy.mapFromSource(src_index)
if index is not None:
src_index = self._projects_model.get_index_by_project_name(
project_name
)
index = self._projects_proxy.mapFromSource(src_index)
if index.isValid():
selection_model = self._projects_view.selectionModel()
selection_model.select(
index,
@ -202,7 +196,7 @@ class TrayPublishWindow(PublisherWindow):
self.setWindowFlags(flags)
overlay_widget = StandaloneOverlayWidget(self)
overlay_widget = StandaloneOverlayWidget(controller, self)
btns_widget = self._header_extra_widget

View file

@ -243,160 +243,3 @@ class RecursiveSortFilterProxyModel(QtCore.QSortFilterProxyModel):
return super(RecursiveSortFilterProxyModel, self).filterAcceptsRow(
row, parent_index
)
# TODO remove 'ProjectModel' and 'ProjectSortFilterProxy' classes
# - replace their usage with current 'ayon_utils' models
class ProjectModel(QtGui.QStandardItemModel):
def __init__(
self, only_active=True, add_default_project=False, *args, **kwargs
):
super(ProjectModel, self).__init__(*args, **kwargs)
self._only_active = only_active
self._add_default_project = add_default_project
self._default_item = None
self._items_by_name = {}
self._refreshed = False
def set_default_project_available(self, available=True):
if available is None:
available = not self._add_default_project
if self._add_default_project == available:
return
self._add_default_project = available
if not available and self._default_item is not None:
root_item = self.invisibleRootItem()
root_item.removeRow(self._default_item.row())
self._default_item = None
def set_only_active(self, only_active=True):
if only_active is None:
only_active = not self._only_active
if self._only_active == only_active:
return
self._only_active = only_active
if self._refreshed:
self.refresh()
def project_name_is_available(self, project_name):
"""Check availability of project name in current items."""
return project_name in self._items_by_name
def refresh(self):
# Change '_refreshed' state
self._refreshed = True
new_items = []
# Add default item to model if should
if self._add_default_project and self._default_item is None:
item = QtGui.QStandardItem(DEFAULT_PROJECT_LABEL)
item.setData(None, PROJECT_NAME_ROLE)
item.setData(True, PROJECT_IS_ACTIVE_ROLE)
new_items.append(item)
self._default_item = item
project_names = set()
project_docs = get_projects(
inactive=not self._only_active,
fields=["name", "data.active"]
)
for project_doc in project_docs:
project_name = project_doc["name"]
project_names.add(project_name)
if project_name in self._items_by_name:
item = self._items_by_name[project_name]
else:
item = QtGui.QStandardItem(project_name)
self._items_by_name[project_name] = item
new_items.append(item)
is_active = project_doc.get("data", {}).get("active", True)
item.setData(project_name, PROJECT_NAME_ROLE)
item.setData(is_active, PROJECT_IS_ACTIVE_ROLE)
if not is_active:
font = item.font()
font.setItalic(True)
item.setFont(font)
root_item = self.invisibleRootItem()
for project_name in tuple(self._items_by_name.keys()):
if project_name not in project_names:
item = self._items_by_name.pop(project_name)
root_item.removeRow(item.row())
if new_items:
root_item.appendRows(new_items)
def find_project(self, project_name):
"""
Get index of 'project_name' value.
Args:
project_name (str):
Returns:
(QModelIndex)
"""
val = self._items_by_name.get(project_name)
if val:
return self.indexFromItem(val)
class ProjectSortFilterProxy(QtCore.QSortFilterProxyModel):
def __init__(self, *args, **kwargs):
super(ProjectSortFilterProxy, self).__init__(*args, **kwargs)
self._filter_enabled = True
# Disable case sensitivity
self.setSortCaseSensitivity(QtCore.Qt.CaseInsensitive)
def lessThan(self, left_index, right_index):
if left_index.data(PROJECT_NAME_ROLE) is None:
return True
if right_index.data(PROJECT_NAME_ROLE) is None:
return False
left_is_active = left_index.data(PROJECT_IS_ACTIVE_ROLE)
right_is_active = right_index.data(PROJECT_IS_ACTIVE_ROLE)
if right_is_active == left_is_active:
return super(ProjectSortFilterProxy, self).lessThan(
left_index, right_index
)
if left_is_active:
return True
return False
def filterAcceptsRow(self, source_row, source_parent):
index = self.sourceModel().index(source_row, 0, source_parent)
string_pattern = self.filterRegularExpression().pattern()
if self._filter_enabled:
result = self._custom_index_filter(index)
if result is not None:
project_name = index.data(PROJECT_NAME_ROLE)
if project_name is None:
return result
return string_pattern.lower() in project_name.lower()
return super(ProjectSortFilterProxy, self).filterAcceptsRow(
source_row, source_parent
)
def _custom_index_filter(self, index):
is_active = bool(index.data(PROJECT_IS_ACTIVE_ROLE))
return is_active
def is_filter_enabled(self):
return self._filter_enabled
def set_filter_enabled(self, value):
self._filter_enabled = value
self.invalidateFilter()