refactor color list widget to implement edit functionality and improve UI interactions

This commit is contained in:
2025-09-07 13:22:31 +02:00
parent 9d60843ec5
commit 9d389e6e5f

View File

@@ -2,18 +2,11 @@ from PySide6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QListView,
QAbstractItemView, QComboBox, QLabel, QStyledItemDelegate, QStyleOptionButton, QStyle,
)
from PySide6.QtGui import QPixmap, QIcon, QColor, QStandardItemModel, QStandardItem
from PySide6.QtCore import Qt, QSortFilterProxyModel, QSize, QRect, Signal, QModelIndex, QEvent
from PySide6.QtGui import QPixmap, QIcon, QColor, QStandardItemModel, QStandardItem, QPainter, QCursor
from PySide6.QtCore import Qt, QSortFilterProxyModel, QSize, QRect, Signal, QModelIndex, QEvent, QItemSelectionModel
import sys
def color_icon(color: QColor, size: int = 24) -> QIcon:
pixmap = QPixmap(size, size)
pixmap.fill(color)
return QIcon(pixmap)
class FilterProxy(QSortFilterProxyModel):
def __init__(self, parent=None):
super().__init__(parent)
@@ -31,29 +24,42 @@ class FilterProxy(QSortFilterProxyModel):
name = model.data(index, Qt.ItemDataRole.DisplayRole)
return self.search_text.lower() in name.lower()
class DeleteButtonDelegate(QStyledItemDelegate):
deleteClicked = Signal(QModelIndex)
class EditButtonDelegate(QStyledItemDelegate):
editClicked = Signal(QModelIndex)
def __init__(self, parent=None):
super().__init__(parent)
self.button_clicked_row = None
self.margin = 8
def paint(self, painter, option, index):
super().paint(painter, option, index)
button = QStyleOptionButton()
button.rect = QRect(option.rect.right() - 60, option.rect.top(), 60, option.rect.height()) # type: ignore
button.text = "Usuń" # type: ignore
QApplication.style().drawControl(QStyle.ControlElement.CE_PushButton, button, painter)
if option.state & QStyle.StateFlag.State_MouseOver:
button = QStyleOptionButton()
button.rect = QRect(option.rect.right() - 60, option.rect.top() + self.margin , 60, option.rect.height() - self.margin * 2) # type: ignore
button.text = "EDYTUJ" # type: ignore
QApplication.style().drawControl(QStyle.ControlElement.CE_PushButton, button, painter)
def editorEvent(self, event, model, option, index):
button_rect = QRect(option.rect.right() - 60, option.rect.top() + self.margin , 60, option.rect.height() - self.margin * 2)
if event.type() == QEvent.Type.MouseButtonRelease:
button_rect = QRect(option.rect.right() - 60, option.rect.top(), 60, option.rect.height())
# button_rect = QRect(option.rect.right() - 60, option.rect.top(), 60, option.rect.height())
if button_rect.contains(event.pos()):
self.deleteClicked.emit(index)
self.button_clicked_row = index.row()
self.editClicked.emit(index)
return True
return super().editorEvent(event, model, option, index)
class ColorListWidget(QWidget):
def __init__(self, colors: list[dict], parent=None):
editColor = Signal(str)
def __init__(self, parent=None):
super().__init__(parent)
self.colors = colors
self.colors = None
layout = QVBoxLayout(self)
@@ -62,74 +68,54 @@ class ColorListWidget(QWidget):
self.filter_edit.setMinimumHeight(32)
self.filter_edit.setStyleSheet("font-size: 12pt;")
edit_clear = self.filter_edit.addAction(QIcon.fromTheme(QIcon.ThemeIcon.EditClear), QLineEdit.ActionPosition.TrailingPosition)
edit_clear.triggered.connect(lambda: self.filter_edit.clear())
layout.addWidget(self.filter_edit)
self.model = QStandardItemModel(self)
if colors:
self.set_colors(colors)
# for color in colors:
# item = QStandardItem( color['name'])
# item.setIcon(color_icon(QColor(color['hex']), 112))
# self.model.appendRow(item)
self.proxy_model = FilterProxy(self)
self.proxy_model.setSourceModel(self.model)
self.list_view = QListView()
self.list_view.setModel(self.proxy_model)
# self.list_view.setModel(self.model)
self.list_view.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
self.list_view.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
self.list_view.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectItems)
self.list_view.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
self.list_view.setUniformItemSizes(True)
self.list_view.setSpacing(2)
self.list_view.setIconSize(QSize(36, 36))
self.list_view.setStyleSheet("""
QListView::icon {
margin-right: 12px; /* odstęp między ikoną a tekstem */
}
""")
self.list_view.setMouseTracking(True)
layout.addWidget(self.list_view)
delegate = DeleteButtonDelegate(self.list_view)
delegate.deleteClicked.connect(self.on_delete_item)
self.list_view.setItemDelegate(delegate)
self.delegate = EditButtonDelegate(self.list_view)
self.delegate.editClicked.connect(self.on_edit_clicked)
self.list_view.setItemDelegate(self.delegate)
self.filter_edit.textChanged.connect(self.proxy_model.setSearchText)
# self.list_view.selectionModel().selectionChanged.connect(self.on_selection_changed)
self.list_view.selectionModel().currentChanged.connect(self.on_current_changed)
self.filter_edit.textChanged.connect(self.on_filter_changed)
self.list_view.clicked.connect(self.on_item_clicked)
def set_colors(self, colors: list[dict]):
self.colors = colors
def on_filter_changed(self, text: str):
self.proxy_model.setSearchText(text)
self.list_view.clearSelection()
def set_colors(self, db_colors: list[dict]):
self.model.clear()
for color in colors:
for color in db_colors:
item = QStandardItem( color['name'])
item.setIcon(color_icon(QColor(color['color']), 112))
item.setIcon(QIcon(color['icon_path']))
self.model.appendRow(item)
def on_current_changed(self, current, previous):
if current.isValid():
source_index = self.proxy_model.mapToSource(current)
item = self.model.itemFromIndex(source_index)
print(f"Wybrano kolor: {item.text()}")
def on_selection_changed(self, selected, deselected):
indexes = selected.indexes()
if indexes:
index = indexes[0]
source_index = self.proxy_model.mapToSource(index)
item = self.model.itemFromIndex(source_index)
line = item.text()
print(f"Wybrano kolor: {line}")
return line
else:
line = ""
print("Brak zaznaczenia")
return line
def on_item_clicked(self, index):
if self.delegate.button_clicked_row == index.row():
self.delegate.button_clicked_row = None
return
self.list_view.selectionModel().select(index, QItemSelectionModel.SelectionFlag.ClearAndSelect)
source_index = self.proxy_model.mapToSource(index)
item = self.model.itemFromIndex(source_index)
if item:
@@ -137,6 +123,11 @@ class ColorListWidget(QWidget):
print(f"Kliknięto kolor: {line}")
return line
def on_delete_item(self, index):
def on_edit_clicked(self, index):
source_index = self.proxy_model.mapToSource(index)
self.model.removeRow(source_index.row())
# print("Edit:", self.model.itemFromIndex(source_index).text())
item = self.model.itemFromIndex(source_index)
if item:
line = item.text()
print(f"Edycja koloru: {line}")
self.editColor.emit(line)