mirror of
https://github.com/283375/arcaea-offline-pyside-ui.git
synced 2025-04-16 07:40:18 +00:00
impr: TextSegmentDelegate
improvements
This commit is contained in:
parent
cf913d296e
commit
8628399469
@ -25,12 +25,28 @@ class TextSegmentDelegate(QStyledItemDelegate):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
# TODO: make this differ by index
|
||||
self.baseXOffset = 0
|
||||
self.baseYOffset = 0
|
||||
self.baseXOffsets: dict[str, int] = {}
|
||||
self.baseYOffsets: dict[str, int] = {}
|
||||
|
||||
self.verticalAlign = TextSegmentDelegateVerticalAlign.Middle
|
||||
|
||||
def indexOffsetKey(self, index: QModelIndex):
|
||||
return f"{index.row()},{index.column()}"
|
||||
|
||||
def setBaseXOffset(self, index: QModelIndex, offset: int):
|
||||
key = self.indexOffsetKey(index)
|
||||
if not offset:
|
||||
self.baseXOffsets.pop(key, None)
|
||||
else:
|
||||
self.baseXOffsets[key] = offset
|
||||
|
||||
def setBaseYOffset(self, index: QModelIndex, offset: int):
|
||||
key = self.indexOffsetKey(index)
|
||||
if not offset:
|
||||
self.baseYOffsets.pop(key, None)
|
||||
else:
|
||||
self.baseYOffsets[key] = offset
|
||||
|
||||
def setVerticalAlign(self, align: Literal["top", "middle", "bottom"]):
|
||||
if not isinstance(align, str) and align not in ["top", "middle", "bottom"]:
|
||||
raise ValueError(
|
||||
@ -60,12 +76,14 @@ class TextSegmentDelegate(QStyledItemDelegate):
|
||||
]:
|
||||
return []
|
||||
|
||||
def sizeHint(self, option, index) -> QSize:
|
||||
def textsSizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) -> QSize:
|
||||
width = 0
|
||||
height = self.VerticalPadding
|
||||
height = 0
|
||||
fm: QFontMetrics = option.fontMetrics
|
||||
for line in self.getTextSegments(index, option):
|
||||
lineWidth = 4 * self.HorizontalPadding
|
||||
segments = self.getTextSegments(index, option)
|
||||
for i in range(len(segments)):
|
||||
line = segments[i]
|
||||
lineWidth = 2 * self.HorizontalPadding
|
||||
lineHeight = 0
|
||||
for textFrag in line:
|
||||
font = textFrag.get(self.FontRole)
|
||||
@ -76,14 +94,30 @@ class TextSegmentDelegate(QStyledItemDelegate):
|
||||
lineWidth += textWidth
|
||||
lineHeight = max(lineHeight, textHeight)
|
||||
width = max(lineWidth, width)
|
||||
height += lineHeight + self.VerticalPadding
|
||||
height += lineHeight
|
||||
if i != len(segments) - 1:
|
||||
height += self.VerticalPadding
|
||||
return QSize(width, height)
|
||||
|
||||
def sizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) -> QSize:
|
||||
width = self.HorizontalPadding * 2
|
||||
height = self.VerticalPadding * 2
|
||||
textsSizeHint = self.textsSizeHint(option, index)
|
||||
return QSize(textsSizeHint.width() + width, textsSizeHint.height() + height)
|
||||
|
||||
def baseX(self, option: QStyleOptionViewItem, index: QModelIndex):
|
||||
return option.rect.x() + self.HorizontalPadding + self.baseXOffset
|
||||
return (
|
||||
option.rect.x()
|
||||
+ self.HorizontalPadding
|
||||
+ self.baseXOffsets.get(self.indexOffsetKey(index), 0)
|
||||
)
|
||||
|
||||
def baseY(self, option: QStyleOptionViewItem, index: QModelIndex):
|
||||
baseY = option.rect.y() + self.VerticalPadding + self.baseYOffset
|
||||
baseY = (
|
||||
option.rect.y()
|
||||
+ self.VerticalPadding
|
||||
+ self.baseYOffsets.get(self.indexOffsetKey(index), 0)
|
||||
)
|
||||
if self.verticalAlign != TextSegmentDelegateVerticalAlign.Top:
|
||||
paintAreaSize: QSize = option.rect.size()
|
||||
delegateSize = self.sizeHint(option, index)
|
||||
@ -94,7 +128,11 @@ class TextSegmentDelegate(QStyledItemDelegate):
|
||||
return baseY
|
||||
|
||||
def textMaxWidth(self, option: QStyleOptionViewItem, index: QModelIndex):
|
||||
return option.rect.width() - (2 * self.HorizontalPadding) - self.baseXOffset
|
||||
return (
|
||||
option.rect.width()
|
||||
- (2 * self.HorizontalPadding)
|
||||
- self.baseXOffsets.get(self.indexOffsetKey(index), 0)
|
||||
)
|
||||
|
||||
def paint(
|
||||
self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex
|
||||
|
@ -1,7 +1,7 @@
|
||||
from arcaea_offline.models import Chart, Difficulty, Song
|
||||
from arcaea_offline.utils.rating import rating_class_to_short_text, rating_class_to_text
|
||||
from PIL import Image
|
||||
from PySide6.QtCore import QModelIndex, Qt, Signal
|
||||
from PySide6.QtCore import QModelIndex, QRect, Qt, Signal
|
||||
from PySide6.QtGui import QColor, QPainter, QPixmap
|
||||
from PySide6.QtWidgets import (
|
||||
QFrame,
|
||||
@ -173,7 +173,9 @@ class ChartDelegate(TextSegmentDelegate):
|
||||
|
||||
def sizeHint(self, option, index):
|
||||
size = super().sizeHint(option, index)
|
||||
size.setWidth(size.width() + self.HorizontalPadding + size.height())
|
||||
minWidth = size.height() + 2 * self.HorizontalPadding # jacket size
|
||||
width = size.width() + self.HorizontalPadding + size.height()
|
||||
size.setWidth(max(minWidth, width))
|
||||
return size
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
@ -193,12 +195,13 @@ class ChartDelegate(TextSegmentDelegate):
|
||||
jacketPath = "__TEXT_ONLY__"
|
||||
|
||||
if jacketPath == "__TEXT_ONLY__":
|
||||
self.setBaseXOffset(index, 0)
|
||||
super().paint(painter, option, index)
|
||||
return
|
||||
|
||||
textSizeHint = super().sizeHint(option, index)
|
||||
jacketSize = textSizeHint.height()
|
||||
self.baseXOffset = self.HorizontalPadding + jacketSize
|
||||
textsSizeHint = super().textsSizeHint(option, index)
|
||||
jacketSize = textsSizeHint.height()
|
||||
self.setBaseXOffset(index, self.HorizontalPadding + jacketSize)
|
||||
|
||||
jacketSizeTuple = (jacketSize, jacketSize)
|
||||
if jacketPath:
|
||||
@ -214,11 +217,21 @@ class ChartDelegate(TextSegmentDelegate):
|
||||
.toqpixmap()
|
||||
)
|
||||
|
||||
pixmapAvailableWidth = option.rect.width() - self.HorizontalPadding
|
||||
pixmapAvailableHeight = option.rect.height()
|
||||
|
||||
if pixmapAvailableWidth < jacketSize or pixmapAvailableHeight < jacketSize:
|
||||
cropRect = QRect(0, 0, pixmapAvailableWidth, pixmapAvailableHeight)
|
||||
pixmap = pixmap.copy(cropRect)
|
||||
|
||||
painter.save()
|
||||
painter.setRenderHint(QPainter.RenderHint.LosslessImageRendering, True)
|
||||
painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
|
||||
pixmapBaseY = self.baseY(option, index)
|
||||
painter.drawPixmap(
|
||||
option.rect.x() + self.HorizontalPadding, self.baseY(option, index), pixmap
|
||||
option.rect.x() + self.HorizontalPadding,
|
||||
pixmapBaseY,
|
||||
pixmap,
|
||||
)
|
||||
painter.restore()
|
||||
super().paint(painter, option, index)
|
||||
|
Loading…
x
Reference in New Issue
Block a user