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