""" Виджет для управления слоями изображений """ from PySide6.QtWidgets import ( QWidget, QVBoxLayout, QListWidget, QListWidgetItem, QHBoxLayout, QCheckBox, QSlider, QLabel, QPushButton, QFrame ) from PySide6.QtCore import Qt, Signal, QSize class LayerWidgetItem(QWidget): """Виджет для отдельного слоя в списке""" visibility_toggled = Signal(int, bool) opacity_changed = Signal(int, float) def __init__(self, layer_id: int, name: str, visible: bool = True): super().__init__() self.layer_id = layer_id self.init_ui(name, visible) def init_ui(self, name: str, visible: bool): layout = QHBoxLayout(self) layout.setContentsMargins(8, 6, 8, 6) layout.setSpacing(8) # Чекбокс видимости self.visibility_checkbox = QCheckBox() self.visibility_checkbox.setChecked(visible) self.visibility_checkbox.setFixedSize(22, 22) self.visibility_checkbox.toggled.connect(self.on_visibility_toggled) layout.addWidget(self.visibility_checkbox) # Название слоя self.name_label = QLabel(name) self.name_label.setStyleSheet("font-size: 11px; font-weight: 500;") self.name_label.setWordWrap(True) layout.addWidget(self.name_label, 2) # Слайдер прозрачности self.opacity_slider = QSlider(Qt.Orientation.Horizontal) self.opacity_slider.setRange(0, 100) self.opacity_slider.setValue(100) self.opacity_slider.setFixedWidth(100) self.opacity_slider.valueChanged.connect(self.on_opacity_changed) layout.addWidget(self.opacity_slider) # Метка прозрачности self.opacity_label = QLabel("100%") self.opacity_label.setFixedWidth(35) self.opacity_label.setStyleSheet("font-size: 10px; font-family: monospace;") layout.addWidget(self.opacity_label) # Кнопка удаления remove_button = QPushButton("✖") remove_button.setFixedSize(26, 26) remove_button.setStyleSheet(""" QPushButton { background-color: #e74c3c; color: white; border-radius: 13px; font-size: 12px; font-weight: bold; } QPushButton:hover { background-color: #c0392b; } """) remove_button.clicked.connect(lambda: self.visibility_toggled.emit(self.layer_id, False)) layout.addWidget(remove_button) def on_visibility_toggled(self, checked): self.visibility_toggled.emit(self.layer_id, checked) def on_opacity_changed(self, value): opacity = value / 100.0 self.opacity_label.setText(f"{value}%") self.opacity_changed.emit(self.layer_id, opacity) def set_visible(self, visible: bool): self.visibility_checkbox.setChecked(visible) def set_opacity(self, opacity: float): value = int(opacity * 100) self.opacity_slider.setValue(value) self.opacity_label.setText(f"{value}%") class LayerWidget(QWidget): """Виджет для отображения списка слоев""" def __init__(self, controller): super().__init__() self.controller = controller self.layer_widgets = {} self.init_ui() def init_ui(self): layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(5) # Список слоев self.list_widget = QListWidget() self.list_widget.setStyleSheet(""" QListWidget { border: 1px solid #555; border-radius: 5px; background-color: #2b2b2b; outline: none; } QListWidget::item { border-bottom: 1px solid #444; } QListWidget::item:selected { background-color: #3c5a8c; } QListWidget::item:hover { background-color: #3c3c3c; } """) layout.addWidget(self.list_widget) # Кнопка очистки clear_button = QPushButton("🗑️ Очистить все слои") clear_button.setMinimumHeight(32) clear_button.setStyleSheet(""" QPushButton { background-color: #555; color: white; padding: 5px; border-radius: 4px; } QPushButton:hover { background-color: #e74c3c; } """) clear_button.clicked.connect(self.clear_all_layers) layout.addWidget(clear_button) # Пустое состояние self.empty_label = QLabel("📭 Нет загруженных слоев\n\nНажмите 'Загрузить изображение'") self.empty_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.empty_label.setStyleSheet("color: #888; padding: 30px; background-color: #2b2b2b; border-radius: 5px;") self.empty_label.setVisible(True) layout.addWidget(self.empty_label) def add_layer(self, layer_id: int, name: str, visible: bool = True): """Добавляет новый слой в список""" self.empty_label.setVisible(False) self.list_widget.setVisible(True) item = QListWidgetItem() item.setSizeHint(QSize(0, 55)) self.list_widget.addItem(item) widget = LayerWidgetItem(layer_id, name, visible) widget.visibility_toggled.connect(self.on_visibility_toggled) widget.opacity_changed.connect(self.on_opacity_changed) self.list_widget.setItemWidget(item, widget) self.layer_widgets[layer_id] = (item, widget) self.list_widget.setCurrentItem(item) self.list_widget.scrollToItem(item) def remove_layer(self, layer_id: int): """Удаляет слой из списка""" if layer_id in self.layer_widgets: item, _ = self.layer_widgets[layer_id] row = self.list_widget.row(item) self.list_widget.takeItem(row) del self.layer_widgets[layer_id] if len(self.layer_widgets) == 0: self.empty_label.setVisible(True) self.list_widget.setVisible(False) def update_layers(self, layers): """Обновляет весь список слоев""" self.clear_all_layers(keep_controller=False) for layer in layers: self.add_layer(layer.id, layer.name, layer.visible) if layers: self.empty_label.setVisible(False) self.list_widget.setVisible(True) else: self.empty_label.setVisible(True) self.list_widget.setVisible(False) def clear_all_layers(self, keep_controller: bool = True): """Очищает список слоев""" self.list_widget.clear() self.layer_widgets.clear() if keep_controller: self.controller.clear_all_layers() self.empty_label.setVisible(True) self.list_widget.setVisible(False) def on_visibility_toggled(self, layer_id: int, visible: bool): self.controller.set_layer_visibility(layer_id, visible) def on_opacity_changed(self, layer_id: int, opacity: float): self.controller.set_layer_opacity(layer_id, opacity) def get_selected_layer_id(self) -> int: current_item = self.list_widget.currentItem() if current_item: for layer_id, (item, _) in self.layer_widgets.items(): if item == current_item: return layer_id return None def get_layers_count(self) -> int: return len(self.layer_widgets)