72 lines
2.2 KiB
Python
72 lines
2.2 KiB
Python
"""Square 1:1 image panel host for dashboard viewports."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from PyQt5.QtCore import Qt
|
|
from PyQt5.QtGui import QPixmap
|
|
from PyQt5.QtWidgets import QLabel, QSizePolicy, QVBoxLayout, QWidget
|
|
|
|
from .qt_pixmap import pixmap_keep_aspect
|
|
|
|
|
|
class ImagePanel(QWidget):
|
|
"""Fixed square widget that displays an image at 1:1 aspect ratio."""
|
|
|
|
def __init__(
|
|
self,
|
|
*,
|
|
title: str = "",
|
|
object_name: str = "panelLabel",
|
|
default_side: int = 256,
|
|
min_side: int = 64,
|
|
parent=None,
|
|
):
|
|
super().__init__(parent)
|
|
self._side = default_side
|
|
self._min_side = min_side
|
|
self._source_pixmap: QPixmap | None = None
|
|
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
|
|
|
|
layout = QVBoxLayout(self)
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
self.label = QLabel(title)
|
|
self.label.setObjectName(object_name)
|
|
self.label.setAlignment(Qt.AlignCenter)
|
|
layout.addWidget(self.label)
|
|
self.set_side_length(self._side)
|
|
|
|
def set_side_length(self, side: int) -> None:
|
|
self.set_fixed_size(side, side)
|
|
|
|
def set_fixed_size(self, width: int, height: int) -> None:
|
|
width = max(int(width), self._min_side)
|
|
height = max(int(height), self._min_side)
|
|
if width == self.width() and height == self.height() and width == self._side:
|
|
return
|
|
self._side = width
|
|
self.setFixedSize(width, height)
|
|
self.label.setFixedSize(width, height)
|
|
self.on_side_length_changed(min(width, height))
|
|
self._refresh_pixmap()
|
|
|
|
@property
|
|
def side_length(self) -> int:
|
|
return self._side
|
|
|
|
def on_side_length_changed(self, side: int) -> None:
|
|
"""Hook for subclasses (e.g. resize an offscreen renderer)."""
|
|
|
|
def set_source_pixmap(self, pixmap: QPixmap | None) -> None:
|
|
self._source_pixmap = pixmap
|
|
self._refresh_pixmap()
|
|
|
|
def _refresh_pixmap(self) -> None:
|
|
if self._source_pixmap is None or self._source_pixmap.isNull():
|
|
return
|
|
self.label.setPixmap(pixmap_keep_aspect(self._source_pixmap, self.label.size()))
|
|
|
|
def resizeEvent(self, event):
|
|
super().resizeEvent(event)
|
|
self._refresh_pixmap()
|