Files
Dispatch/Dispatch_V0.1.1/ui/cards/task_card_pixmap_factory.py
2026-04-29 08:18:54 +04:00

130 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
# hub/ticket/ui/cards/task_card_pixmap_factory.py
"""Pixmap-хелперы для карточки Ticket."""
from __future__ import annotations
from PySide6.QtCore import Qt
from PySide6.QtGui import QColor, QFont, QPainter, QPainterPath, QPixmap
def compute_square_size(width: int, height: int, padding: int = 0) -> int:
"""Вернуть квадратный размер по меньшей стороне с учётом внутреннего отступа."""
available = min(width, height) - padding
return max(0, available)
def build_avatar_pixmap(source: QPixmap, size: int) -> QPixmap:
"""Построить круглый avatar-pixmap из исходной фотографии."""
avatar = QPixmap(size, size)
avatar.fill(Qt.GlobalColor.transparent)
painter = QPainter(avatar)
painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
outer_padding = 1
outer_size = size - (outer_padding * 2)
outer_path = QPainterPath()
outer_path.addEllipse(outer_padding, outer_padding, outer_size, outer_size)
painter.fillPath(outer_path, QColor("#A3A3A3"))
inner_padding = outer_padding + 2
inner_size = size - (inner_padding * 2)
inner_path = QPainterPath()
inner_path.addEllipse(inner_padding, inner_padding, inner_size, inner_size)
painter.setClipPath(inner_path)
scaled = source.scaled(
inner_size,
inner_size,
Qt.AspectRatioMode.KeepAspectRatioByExpanding,
Qt.TransformationMode.SmoothTransformation,
)
source_x = max(0, (scaled.width() - inner_size) // 2)
source_y = max(0, (scaled.height() - inner_size) // 2)
painter.drawPixmap(inner_padding, inner_padding, scaled, source_x, source_y, inner_size, inner_size)
painter.end()
return avatar
def build_placeholder_avatar_pixmap(size: int) -> QPixmap:
"""Построить круглый placeholder-аватар с вопросительным знаком."""
avatar = QPixmap(size, size)
avatar.fill(Qt.GlobalColor.transparent)
painter = QPainter(avatar)
painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
outer_padding = 1
circle_size = size - (outer_padding * 2)
circle_path = QPainterPath()
circle_path.addEllipse(outer_padding, outer_padding, circle_size, circle_size)
painter.fillPath(circle_path, QColor("#F6A493"))
painter.setPen(QColor("#FFFFFF"))
painter.drawPath(circle_path)
font = QFont()
font.setPixelSize(18)
font.setBold(True)
painter.setFont(font)
painter.setPen(QColor("#172B4D"))
painter.drawText(outer_padding, outer_padding, circle_size, circle_size, Qt.AlignmentFlag.AlignCenter, "?")
painter.end()
return avatar
def load_scaled_icon_pixmap(image_path: str, width: int, height: int, padding: int = 0) -> QPixmap | None:
"""Загрузить и отмасштабировать stage-icon по фактическому размеру ячейки."""
if not image_path:
return None
pixmap = QPixmap(image_path)
if pixmap.isNull():
return None
icon_size = compute_square_size(width, height, padding)
if icon_size <= 0:
return None
return pixmap.scaled(
icon_size,
icon_size,
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation,
)
def load_tinted_icon_pixmap(
image_path: str,
width: int,
height: int,
color_hex: str,
padding: int = 0,
) -> QPixmap | None:
"""Загрузить stage-icon и перекрасить его в нужный цвет."""
scaled = load_scaled_icon_pixmap(image_path, width, height, padding)
if scaled is None:
return None
tinted = QPixmap(scaled.size())
tinted.fill(Qt.GlobalColor.transparent)
painter = QPainter(tinted)
painter.drawPixmap(0, 0, scaled)
painter.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceIn)
painter.fillRect(tinted.rect(), QColor(color_hex))
painter.end()
return tinted
def load_avatar_pixmap(image_path: str, width: int, height: int, padding: int = 0) -> QPixmap | None:
"""Загрузить фото специалиста и подготовить круглый avatar-pixmap."""
if not image_path:
return None
pixmap = QPixmap(image_path)
if pixmap.isNull():
return None
avatar_size = compute_square_size(width, height, padding)
if avatar_size <= 0:
return None
return build_avatar_pixmap(pixmap, avatar_size)