fuck yeah!
This commit is contained in:
parent
ccb53d9091
commit
da10f5e132
44 changed files with 3260 additions and 448 deletions
219
views/layer_widget.py
Normal file
219
views/layer_widget.py
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
"""
|
||||
Виджет для управления слоями изображений
|
||||
"""
|
||||
|
||||
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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue