mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 12:54:40 +01:00
Merge 59d9147cf4 into b6b2726795
This commit is contained in:
commit
04cac8d26d
2 changed files with 119 additions and 8 deletions
|
|
@ -133,8 +133,8 @@ class UnderlinesFolderDelegate(QtWidgets.QItemDelegate):
|
|||
mode = QtGui.QIcon.Selected
|
||||
|
||||
if isinstance(icon, QtGui.QPixmap):
|
||||
icon = QtGui.QIcon(icon)
|
||||
option.decorationSize = icon.size() / icon.devicePixelRatio()
|
||||
icon = QtGui.QIcon(icon)
|
||||
|
||||
elif isinstance(icon, QtGui.QColor):
|
||||
pixmap = QtGui.QPixmap(option.decorationSize)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ from ayon_core.tools.common_models import (
|
|||
ProjectsModel,
|
||||
HierarchyModel,
|
||||
HierarchyExpectedSelection,
|
||||
FolderItem
|
||||
)
|
||||
import ayon_api
|
||||
|
||||
from .models import RecursiveSortFilterProxyModel
|
||||
from .views import TreeView
|
||||
|
|
@ -26,6 +28,89 @@ FOLDER_PATH_ROLE = QtCore.Qt.UserRole + 3
|
|||
FOLDER_TYPE_ROLE = QtCore.Qt.UserRole + 4
|
||||
|
||||
|
||||
class ImageLoader(QtCore.QThread):
|
||||
image_loaded = QtCore.Signal(QtGui.QStandardItem, QtGui.QImage)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self._image_queue = collections.deque()
|
||||
|
||||
# Turn this into a 'timed' cache to allow refresh after a certain time
|
||||
self._cache = {}
|
||||
self._thread = QtCore.QThread()
|
||||
|
||||
def load_image(self,
|
||||
item: QtGui.QStandardItem,
|
||||
project_name: str,
|
||||
entity_id: str):
|
||||
# If image is in cache, do nothing
|
||||
if (project_name, entity_id) in self._cache:
|
||||
return
|
||||
|
||||
self._image_queue.append((item, project_name, entity_id))
|
||||
if not self.isRunning():
|
||||
self.start()
|
||||
|
||||
def get_image(self, project_name, entity_id):
|
||||
return self._cache.get((project_name, entity_id), None)
|
||||
|
||||
def run(self):
|
||||
# Process remaining queue
|
||||
while self._image_queue:
|
||||
item, project_name, entity_id = self._image_queue.popleft()
|
||||
|
||||
# Query thumbnail from server
|
||||
# TODO: Get these from a cache instead of querying every time
|
||||
response = ayon_api.raw_get(
|
||||
f"projects/{project_name}/folders/{entity_id}/thumbnail")
|
||||
image_bytes = response.content
|
||||
|
||||
# TODO: Skip if image is empty or not valid
|
||||
# this does not work
|
||||
if not image_bytes:
|
||||
continue
|
||||
|
||||
# Get image format
|
||||
# https://doc.qt.io/qt-6/qimagereader.html#supportedImageFormats
|
||||
image_type = response.headers['content-type']
|
||||
if image_type == "image/jpeg":
|
||||
image_format = "JPG"
|
||||
elif image_type == "image/png":
|
||||
image_format = "PNG"
|
||||
else:
|
||||
raise TypeError(f"Unsupported image type: {image_type}")
|
||||
|
||||
# Load the image from the bytes
|
||||
image = QtGui.QImage()
|
||||
image.loadFromData(image_bytes, image_format)
|
||||
|
||||
# Not a valid image.
|
||||
if image.isNull() or (image.width() == 1 and image.height() == 1):
|
||||
self._cache[(project_name, entity_id)] = None
|
||||
continue
|
||||
|
||||
# Scale down and maintain aspect ratio of the image
|
||||
# but crop and center it to 16:9
|
||||
icon_width = 112
|
||||
icon_height = 63
|
||||
image = image.scaled(icon_width, icon_height,
|
||||
QtCore.Qt.KeepAspectRatioByExpanding,
|
||||
QtCore.Qt.SmoothTransformation)
|
||||
|
||||
# Create a 32x32 square and center the image
|
||||
square_image = QtGui.QImage(
|
||||
icon_width, icon_height, QtGui.QImage.Format_ARGB32)
|
||||
square_image.fill(QtCore.Qt.transparent)
|
||||
painter = QtGui.QPainter(square_image)
|
||||
x = (icon_width - image.width()) // 2
|
||||
y = (icon_height - image.height()) // 2
|
||||
painter.drawImage(x, y, image)
|
||||
painter.end()
|
||||
|
||||
self._cache[(project_name, entity_id)] = square_image
|
||||
self.image_loaded.emit(item, square_image)
|
||||
|
||||
|
||||
class FoldersQtModel(QtGui.QStandardItemModel):
|
||||
"""Folders model which cares about refresh of folders.
|
||||
|
||||
|
|
@ -53,6 +138,9 @@ class FoldersQtModel(QtGui.QStandardItemModel):
|
|||
self._has_content = False
|
||||
self._is_refreshing = False
|
||||
|
||||
self._image_loader = ImageLoader()
|
||||
self._image_loader.image_loaded.connect(self._on_image_loaded)
|
||||
|
||||
@property
|
||||
def is_refreshing(self):
|
||||
"""Model is refreshing.
|
||||
|
|
@ -236,7 +324,7 @@ class FoldersQtModel(QtGui.QStandardItemModel):
|
|||
def _fill_item_data(
|
||||
self,
|
||||
item,
|
||||
folder_item,
|
||||
folder_item: FolderItem,
|
||||
folder_type_item_by_name,
|
||||
folder_type_icon_cache
|
||||
):
|
||||
|
|
@ -245,19 +333,42 @@ class FoldersQtModel(QtGui.QStandardItemModel):
|
|||
Args:
|
||||
item (QtGui.QStandardItem): Item to fill data.
|
||||
folder_item (FolderItem): Folder item.
|
||||
folder_type_item_by_name (dict): Folder type items by name.
|
||||
folder_type_icon_cache (dict): Folder type icon cache.
|
||||
|
||||
"""
|
||||
icon = self._get_folder_item_icon(
|
||||
folder_item,
|
||||
folder_type_item_by_name,
|
||||
folder_type_icon_cache
|
||||
)
|
||||
item.setData(folder_item.entity_id, FOLDER_ID_ROLE)
|
||||
item.setData(folder_item.name, FOLDER_NAME_ROLE)
|
||||
item.setData(folder_item.path, FOLDER_PATH_ROLE)
|
||||
item.setData(folder_item.folder_type, FOLDER_TYPE_ROLE)
|
||||
item.setData(folder_item.label, QtCore.Qt.DisplayRole)
|
||||
item.setData(icon, QtCore.Qt.DecorationRole)
|
||||
|
||||
project_name = self.get_project_name()
|
||||
image = self._image_loader.get_image(project_name,
|
||||
folder_item.entity_id)
|
||||
if image:
|
||||
pixmap = QtGui.QPixmap.fromImage(image)
|
||||
#item.setIcon(QtGui.QIcon(pixmap))
|
||||
item.setData(pixmap, QtCore.Qt.DecorationRole)
|
||||
else:
|
||||
icon = self._get_folder_item_icon(
|
||||
folder_item,
|
||||
folder_type_item_by_name,
|
||||
folder_type_icon_cache
|
||||
)
|
||||
item.setData(icon, QtCore.Qt.DecorationRole)
|
||||
|
||||
self._image_loader.load_image(
|
||||
item,
|
||||
project_name=project_name,
|
||||
entity_id=folder_item.entity_id)
|
||||
|
||||
def _on_image_loaded(self,
|
||||
item: QtGui.QStandardItem,
|
||||
image: QtGui.QImage):
|
||||
pixmap = QtGui.QPixmap.fromImage(image)
|
||||
#item.setIcon(QtGui.QIcon(pixmap))
|
||||
item.setData(pixmap, QtCore.Qt.DecorationRole)
|
||||
|
||||
def _fill_items(self, folder_items_by_id, folder_type_items):
|
||||
if not folder_items_by_id:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue