refactor color list widget to implement edit functionality and improve UI interactions
This commit is contained in:
@@ -2,18 +2,11 @@ from PySide6.QtWidgets import (
|
|||||||
QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QListView,
|
QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QListView,
|
||||||
QAbstractItemView, QComboBox, QLabel, QStyledItemDelegate, QStyleOptionButton, QStyle,
|
QAbstractItemView, QComboBox, QLabel, QStyledItemDelegate, QStyleOptionButton, QStyle,
|
||||||
)
|
)
|
||||||
from PySide6.QtGui import QPixmap, QIcon, QColor, QStandardItemModel, QStandardItem
|
from PySide6.QtGui import QPixmap, QIcon, QColor, QStandardItemModel, QStandardItem, QPainter, QCursor
|
||||||
from PySide6.QtCore import Qt, QSortFilterProxyModel, QSize, QRect, Signal, QModelIndex, QEvent
|
from PySide6.QtCore import Qt, QSortFilterProxyModel, QSize, QRect, Signal, QModelIndex, QEvent, QItemSelectionModel
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def color_icon(color: QColor, size: int = 24) -> QIcon:
|
|
||||||
pixmap = QPixmap(size, size)
|
|
||||||
pixmap.fill(color)
|
|
||||||
return QIcon(pixmap)
|
|
||||||
|
|
||||||
|
|
||||||
class FilterProxy(QSortFilterProxyModel):
|
class FilterProxy(QSortFilterProxyModel):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@@ -31,29 +24,42 @@ class FilterProxy(QSortFilterProxyModel):
|
|||||||
name = model.data(index, Qt.ItemDataRole.DisplayRole)
|
name = model.data(index, Qt.ItemDataRole.DisplayRole)
|
||||||
return self.search_text.lower() in name.lower()
|
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):
|
def paint(self, painter, option, index):
|
||||||
super().paint(painter, option, index)
|
super().paint(painter, option, index)
|
||||||
|
|
||||||
|
if option.state & QStyle.StateFlag.State_MouseOver:
|
||||||
button = QStyleOptionButton()
|
button = QStyleOptionButton()
|
||||||
button.rect = QRect(option.rect.right() - 60, option.rect.top(), 60, option.rect.height()) # type: ignore
|
button.rect = QRect(option.rect.right() - 60, option.rect.top() + self.margin , 60, option.rect.height() - self.margin * 2) # type: ignore
|
||||||
button.text = "Usuń" # type: ignore
|
button.text = "EDYTUJ" # type: ignore
|
||||||
QApplication.style().drawControl(QStyle.ControlElement.CE_PushButton, button, painter)
|
QApplication.style().drawControl(QStyle.ControlElement.CE_PushButton, button, painter)
|
||||||
|
|
||||||
|
|
||||||
def editorEvent(self, event, model, option, index):
|
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:
|
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()):
|
if button_rect.contains(event.pos()):
|
||||||
self.deleteClicked.emit(index)
|
self.button_clicked_row = index.row()
|
||||||
|
self.editClicked.emit(index)
|
||||||
return True
|
return True
|
||||||
return super().editorEvent(event, model, option, index)
|
return super().editorEvent(event, model, option, index)
|
||||||
|
|
||||||
|
|
||||||
class ColorListWidget(QWidget):
|
class ColorListWidget(QWidget):
|
||||||
def __init__(self, colors: list[dict], parent=None):
|
editColor = Signal(str)
|
||||||
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.colors = colors
|
self.colors = None
|
||||||
|
|
||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
|
|
||||||
@@ -62,74 +68,54 @@ class ColorListWidget(QWidget):
|
|||||||
self.filter_edit.setMinimumHeight(32)
|
self.filter_edit.setMinimumHeight(32)
|
||||||
self.filter_edit.setStyleSheet("font-size: 12pt;")
|
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)
|
layout.addWidget(self.filter_edit)
|
||||||
|
|
||||||
self.model = QStandardItemModel(self)
|
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 = FilterProxy(self)
|
||||||
self.proxy_model.setSourceModel(self.model)
|
self.proxy_model.setSourceModel(self.model)
|
||||||
|
|
||||||
self.list_view = QListView()
|
self.list_view = QListView()
|
||||||
self.list_view.setModel(self.proxy_model)
|
self.list_view.setModel(self.proxy_model)
|
||||||
# self.list_view.setModel(self.model)
|
|
||||||
self.list_view.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
|
self.list_view.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
|
||||||
self.list_view.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
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.setUniformItemSizes(True)
|
||||||
self.list_view.setSpacing(2)
|
self.list_view.setSpacing(2)
|
||||||
self.list_view.setIconSize(QSize(36, 36))
|
self.list_view.setIconSize(QSize(36, 36))
|
||||||
self.list_view.setStyleSheet("""
|
self.list_view.setMouseTracking(True)
|
||||||
QListView::icon {
|
|
||||||
margin-right: 12px; /* odstęp między ikoną a tekstem */
|
|
||||||
}
|
|
||||||
""")
|
|
||||||
layout.addWidget(self.list_view)
|
layout.addWidget(self.list_view)
|
||||||
|
|
||||||
delegate = DeleteButtonDelegate(self.list_view)
|
self.delegate = EditButtonDelegate(self.list_view)
|
||||||
delegate.deleteClicked.connect(self.on_delete_item)
|
self.delegate.editClicked.connect(self.on_edit_clicked)
|
||||||
self.list_view.setItemDelegate(delegate)
|
self.list_view.setItemDelegate(self.delegate)
|
||||||
|
|
||||||
self.filter_edit.textChanged.connect(self.proxy_model.setSearchText)
|
self.filter_edit.textChanged.connect(self.on_filter_changed)
|
||||||
# self.list_view.selectionModel().selectionChanged.connect(self.on_selection_changed)
|
|
||||||
self.list_view.selectionModel().currentChanged.connect(self.on_current_changed)
|
|
||||||
self.list_view.clicked.connect(self.on_item_clicked)
|
self.list_view.clicked.connect(self.on_item_clicked)
|
||||||
|
|
||||||
def set_colors(self, colors: list[dict]):
|
def on_filter_changed(self, text: str):
|
||||||
self.colors = colors
|
self.proxy_model.setSearchText(text)
|
||||||
|
self.list_view.clearSelection()
|
||||||
|
|
||||||
|
def set_colors(self, db_colors: list[dict]):
|
||||||
self.model.clear()
|
self.model.clear()
|
||||||
for color in colors:
|
for color in db_colors:
|
||||||
item = QStandardItem( color['name'])
|
item = QStandardItem( color['name'])
|
||||||
item.setIcon(color_icon(QColor(color['color']), 112))
|
item.setIcon(QIcon(color['icon_path']))
|
||||||
self.model.appendRow(item)
|
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):
|
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)
|
source_index = self.proxy_model.mapToSource(index)
|
||||||
item = self.model.itemFromIndex(source_index)
|
item = self.model.itemFromIndex(source_index)
|
||||||
if item:
|
if item:
|
||||||
@@ -137,6 +123,11 @@ class ColorListWidget(QWidget):
|
|||||||
print(f"Kliknięto kolor: {line}")
|
print(f"Kliknięto kolor: {line}")
|
||||||
return line
|
return line
|
||||||
|
|
||||||
def on_delete_item(self, index):
|
def on_edit_clicked(self, index):
|
||||||
source_index = self.proxy_model.mapToSource(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)
|
||||||
|
|||||||
Reference in New Issue
Block a user