108 lines
3.0 KiB
Python
108 lines
3.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Flow Layout 모듈
|
|
칩이나 태그가 자동으로 줄바꿈되는 레이아웃입니다.
|
|
"""
|
|
|
|
from PySide6.QtWidgets import QLayout
|
|
from PySide6.QtCore import Qt, QRect, QPoint, QSize
|
|
|
|
from core.logger import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
class FlowLayout(QLayout):
|
|
"""
|
|
Flow Layout
|
|
|
|
가로 공간이 부족하면 자동으로 다음 줄로 넘어가는 레이아웃입니다.
|
|
칩이나 태그 UI에 사용됩니다.
|
|
"""
|
|
|
|
def __init__(self, parent=None, margin=0, h_spacing=10, v_spacing=10):
|
|
super().__init__(parent)
|
|
self.h_spacing = h_spacing
|
|
self.v_spacing = v_spacing
|
|
self.items = []
|
|
self.setContentsMargins(margin, margin, margin, margin)
|
|
|
|
def addItem(self, item):
|
|
"""아이템 추가"""
|
|
self.items.append(item)
|
|
|
|
def count(self):
|
|
"""아이템 개수"""
|
|
return len(self.items)
|
|
|
|
def itemAt(self, index):
|
|
"""인덱스로 아이템 가져오기"""
|
|
if 0 <= index < len(self.items):
|
|
return self.items[index]
|
|
return None
|
|
|
|
def takeAt(self, index):
|
|
"""인덱스로 아이템 제거"""
|
|
if 0 <= index < len(self.items):
|
|
return self.items.pop(index)
|
|
return None
|
|
|
|
def expandingDirections(self):
|
|
"""확장 방향"""
|
|
return Qt.Orientations(Qt.Orientation(0))
|
|
|
|
def hasHeightForWidth(self):
|
|
"""너비에 따른 높이 지원"""
|
|
return True
|
|
|
|
def heightForWidth(self, width):
|
|
"""너비에 따른 높이 계산"""
|
|
return self._do_layout(QRect(0, 0, width, 0), True)
|
|
|
|
def setGeometry(self, rect):
|
|
"""지오메트리 설정"""
|
|
super().setGeometry(rect)
|
|
self._do_layout(rect, False)
|
|
|
|
def sizeHint(self):
|
|
"""크기 힌트"""
|
|
return self.minimumSize()
|
|
|
|
def minimumSize(self):
|
|
"""최소 크기"""
|
|
size = QSize()
|
|
for item in self.items:
|
|
size = size.expandedTo(item.minimumSize())
|
|
size += QSize(2 * self.contentsMargins().top(), 2 * self.contentsMargins().top())
|
|
return size
|
|
|
|
def _do_layout(self, rect, test_only):
|
|
"""레이아웃 수행"""
|
|
x, y = rect.x(), rect.y()
|
|
line_height = 0
|
|
|
|
for item in self.items:
|
|
wid = item.widget()
|
|
space_x = self.h_spacing
|
|
space_y = self.v_spacing
|
|
next_x = x + item.sizeHint().width() + space_x
|
|
|
|
if next_x - space_x > rect.right() and line_height > 0:
|
|
x = rect.x()
|
|
y = y + line_height + space_y
|
|
next_x = x + item.sizeHint().width() + space_x
|
|
line_height = 0
|
|
|
|
if not test_only:
|
|
item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
|
|
|
|
x = next_x
|
|
line_height = max(line_height, item.sizeHint().height())
|
|
|
|
return y + line_height - rect.y()
|
|
|
|
|
|
|
|
|
|
|