Add Dispatch_V0.1.1

This commit is contained in:
2026-04-29 08:18:54 +04:00
commit a7ede6ded4
404 changed files with 39167 additions and 0 deletions

View File

@@ -0,0 +1,131 @@
# -*- coding: utf-8 -*-
# gui/components/kanban_column.py
"""Переиспользуемая колонка для канбан-доски."""
from typing import List, Optional
from PySide6.QtCore import Signal
from PySide6.QtWidgets import QWidget
from gui.components.kanban_card import KanbanCard
from gui.components.label import Label
from gui.components.springs import VSpring
from gui.containers.h_container import HContainer
from gui.containers.s_container import SContainer
from gui.containers.scroll_container import ScrollContainer
from gui.containers.v_container import VContainer
class KanbanColumn(SContainer):
"""Вертикальная колонка канбан-доски с заголовком и карточками."""
card_clicked = Signal(object)
def __init__(
self,
column_id: object,
title: str = "",
color: str = "#DFE1E6",
style: str = "KANBAN_COLUMN",
parent: Optional[QWidget] = None,
):
super().__init__(
width_percent=20,
margin=[4, 0, 4, 0],
spacing=0,
style=style,
content_fit=True,
parent=parent,
)
self._column_id = column_id
self._color = color
self._cards: List[KanbanCard] = []
self._build_ui(title, color)
@property
def column_id(self) -> object:
"""Идентификатор колонки."""
return self._column_id
@property
def card_count(self) -> int:
"""Количество карточек в колонке."""
return len(self._cards)
def set_title(self, text: str) -> None:
"""Установить заголовок колонки."""
self._title_label.set_text(text)
def update_counter(self) -> None:
"""Обновить текст счётчика."""
self._counter_label.set_text(str(len(self._cards)))
def add_card(self, card: KanbanCard) -> None:
"""Добавить карточку в колонку перед нижней пружиной."""
card.card_clicked.connect(self.card_clicked.emit)
self._card_container.insert_widget(len(self._cards), card)
self._cards.append(card)
self.update_counter()
def remove_card(self, card_id: object) -> Optional[KanbanCard]:
"""Удалить карточку по ID. Возвращает удалённую карточку или None."""
for card in self._cards:
if card.card_id == card_id:
self._cards.remove(card)
self._detach_card(card)
self.update_counter()
return card
return None
def clear_cards(self) -> None:
"""Удалить все карточки из колонки."""
for card in list(self._cards):
self._detach_card(card)
self._cards.clear()
self.update_counter()
def get_card(self, card_id: object) -> Optional[KanbanCard]:
"""Получить карточку по ID."""
for card in self._cards:
if card.card_id == card_id:
return card
return None
def _build_ui(self, title: str, color: str) -> None:
header = HContainer(
height_percent=6,
margin=[8, 6, 8, 2],
parent=self,
)
color_strip = QWidget()
color_strip.setFixedWidth(4)
color_strip.setFixedHeight(16)
color_strip.setStyleSheet(
f"background-color: {color}; border: none; border-radius: 2px;"
)
header.add_widget(color_strip)
self._title_label = Label(title, style="KANBAN_COLUMN_HEADER")
header.add_widget(self._title_label)
header.add_stretch()
self._counter_label = Label("0", style="KANBAN_COUNTER")
self._counter_label.set_fixed_size(24, 24)
header.add_widget(self._counter_label)
self._scroll = ScrollContainer(
orientation="v",
spacing=0,
content_margins=[0, 2, 0, 2],
vertical_scroll_bar_policy="as_needed",
horizontal_scroll_bar_policy="always_off",
parent=self,
)
self._card_container = VContainer(spacing=2, parent=self._scroll)
self._card_container.add_widget(VSpring())
def _detach_card(self, card: KanbanCard) -> None:
self._card_container.remove_widget(card)
card.setParent(None)