Update
This commit is contained in:
699
2023/scripts/animation_tools/dwpicker/widgets.py
Normal file
699
2023/scripts/animation_tools/dwpicker/widgets.py
Normal file
@@ -0,0 +1,699 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from functools import partial
|
||||
from .pyside import QtGui, QtCore, QtWidgets
|
||||
from .colorwheel import ColorDialog
|
||||
from .dialog import get_image_path
|
||||
from .geometry import grow_rect
|
||||
from .path import format_path
|
||||
from .qtutils import icon
|
||||
from .stack import count_panels
|
||||
|
||||
# don't use style sheet like that, find better design
|
||||
TOGGLER_STYLESHEET = (
|
||||
'background: rgb(0, 0, 0, 75); text-align: left; font: bold')
|
||||
X = '✘'
|
||||
V = '✔'
|
||||
|
||||
|
||||
class BoolCombo(QtWidgets.QComboBox):
|
||||
valueSet = QtCore.Signal(bool)
|
||||
|
||||
def __init__(self, state=True, parent=None):
|
||||
super(BoolCombo, self).__init__(parent)
|
||||
self.addItem('True')
|
||||
self.addItem('False')
|
||||
self.setCurrentText(str(state))
|
||||
self.currentIndexChanged.connect(self.current_index_changed)
|
||||
|
||||
def state(self):
|
||||
return self.currentText() == 'True'
|
||||
|
||||
def current_index_changed(self):
|
||||
self.valueSet.emit(self.state())
|
||||
|
||||
|
||||
class BrowseEdit(QtWidgets.QWidget):
|
||||
valueSet = QtCore.Signal(str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(BrowseEdit, self).__init__(parent)
|
||||
|
||||
self.text = QtWidgets.QLineEdit()
|
||||
self.text.returnPressed.connect(self.apply)
|
||||
self.text.focusOutEvent = self.text_focus_out_event
|
||||
self.button = QtWidgets.QToolButton(self)
|
||||
self.button.setIcon(icon('mini-open.png'))
|
||||
self.button.setFixedSize(21, 21)
|
||||
self.button.released.connect(self.browse)
|
||||
|
||||
self.layout = QtWidgets.QHBoxLayout(self)
|
||||
self.layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.layout.setSpacing(0)
|
||||
self.layout.addWidget(self.text)
|
||||
self.layout.addWidget(self.button)
|
||||
|
||||
self._value = self.value()
|
||||
|
||||
def text_focus_out_event(self, _):
|
||||
self.apply()
|
||||
|
||||
def browse(self):
|
||||
filename = get_image_path(self) or ''
|
||||
format_path(filename)
|
||||
if not filename:
|
||||
return
|
||||
self.text.setText(filename)
|
||||
self.apply()
|
||||
|
||||
def apply(self):
|
||||
text = format_path(self.text.text())
|
||||
self.text.setText(text)
|
||||
self.valueSet.emit(text)
|
||||
|
||||
def value(self):
|
||||
value = format(self.text.text())
|
||||
return value if value != '' else None
|
||||
|
||||
def set_value(self, value):
|
||||
self.text.setText(value)
|
||||
|
||||
|
||||
class WidgetToggler(QtWidgets.QPushButton):
|
||||
def __init__(self, label, widget, parent=None):
|
||||
super(WidgetToggler, self).__init__(parent)
|
||||
self.setStyleSheet(TOGGLER_STYLESHEET)
|
||||
self.setText(' v ' + label)
|
||||
self.widget = widget
|
||||
self.setCheckable(True)
|
||||
self.setChecked(True)
|
||||
self.toggled.connect(self._call_toggled)
|
||||
|
||||
def _call_toggled(self, state):
|
||||
if state is True:
|
||||
self.widget.show()
|
||||
self.setText(self.text().replace('>', 'v'))
|
||||
else:
|
||||
self.widget.hide()
|
||||
self.setText(self.text().replace('v', '>'))
|
||||
|
||||
|
||||
class ColorButton(QtWidgets.QAbstractButton):
|
||||
def __init__(self, parent=None):
|
||||
super(ColorButton, self).__init__(parent)
|
||||
self.color = 'grey'
|
||||
self.setFixedSize(21, 21)
|
||||
self.hover = False
|
||||
|
||||
def enterEvent(self, event):
|
||||
self.hover = True
|
||||
self.update()
|
||||
|
||||
def leaveEvent(self, event):
|
||||
self.hover = False
|
||||
self.update()
|
||||
|
||||
def paintEvent(self, event):
|
||||
painter = QtGui.QPainter(self)
|
||||
painter.setBrush(QtGui.QColor(self.color))
|
||||
painter.setPen(QtCore.Qt.black)
|
||||
rect = self.rect()
|
||||
rect.setWidth(rect.width() - 1)
|
||||
rect.setHeight(rect.height() - 1)
|
||||
painter.drawRect(rect)
|
||||
if not self.hover:
|
||||
painter.end()
|
||||
return
|
||||
rect = grow_rect(rect, -3).toRect()
|
||||
pixmap = icon('picker.png').pixmap(rect.size())
|
||||
painter.drawPixmap(rect, pixmap)
|
||||
painter.end()
|
||||
|
||||
|
||||
class ColorEdit(QtWidgets.QWidget):
|
||||
valueSet = QtCore.Signal(str)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(ColorEdit, self).__init__(parent)
|
||||
|
||||
self.color = ColorButton()
|
||||
self.color.released.connect(self.pick_color)
|
||||
self.text = QtWidgets.QLineEdit()
|
||||
self.text.returnPressed.connect(self.apply)
|
||||
self.text.focusInEvent = self.focusInEvent
|
||||
self.text.focusOutEvent = self.focusOutEvent
|
||||
|
||||
self.layout = QtWidgets.QHBoxLayout(self)
|
||||
self.layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.layout.setSpacing(0)
|
||||
self.layout.addWidget(self.color)
|
||||
self.layout.addWidget(self.text)
|
||||
self.layout.setStretchFactor(self.color, 1)
|
||||
self.layout.setStretchFactor(self.text, 5)
|
||||
|
||||
self._value = self.value()
|
||||
|
||||
def focusInEvent(self, event):
|
||||
self._value = self.value()
|
||||
return super(ColorEdit, self).focusInEvent(event)
|
||||
|
||||
def focusOutEvent(self, event):
|
||||
self.apply()
|
||||
return super(ColorEdit, self).focusOutEvent(event)
|
||||
|
||||
def pick_color(self):
|
||||
color = self.text.text() or None
|
||||
dialog = ColorDialog(color)
|
||||
if dialog.exec_():
|
||||
self.text.setText(dialog.colorname())
|
||||
self.color.color = dialog.colorname()
|
||||
self.color.update()
|
||||
self.apply()
|
||||
|
||||
def apply(self):
|
||||
self.color.color = self.value()
|
||||
self.color.update()
|
||||
if self._value != self.value():
|
||||
self.valueSet.emit(self.value())
|
||||
self._value = self.value()
|
||||
|
||||
def value(self):
|
||||
value = self.text.text()
|
||||
return value if value != '' else None
|
||||
|
||||
def set_color(self, color=None):
|
||||
self.color.color = color or 'grey'
|
||||
self.text.setText(color)
|
||||
self.color.update()
|
||||
|
||||
|
||||
class LineEdit(QtWidgets.QLineEdit):
|
||||
valueSet = QtCore.Signal(float)
|
||||
VALIDATOR_CLS = QtGui.QDoubleValidator
|
||||
|
||||
def __init__(self, minimum=None, maximum=None, parent=None):
|
||||
super(LineEdit, self).__init__(parent)
|
||||
self.validator = self.VALIDATOR_CLS() if self.VALIDATOR_CLS else None
|
||||
if minimum is not None:
|
||||
self.validator.setBottom(minimum)
|
||||
if maximum is not None:
|
||||
self.validator.setTop(maximum)
|
||||
self.setValidator(self.validator)
|
||||
self._value = self.value()
|
||||
self.returnPressed.connect(self.apply)
|
||||
|
||||
def focusInEvent(self, event):
|
||||
self._value = self.value()
|
||||
return super(LineEdit, self).focusInEvent(event)
|
||||
|
||||
def focusOutEvent(self, event):
|
||||
self.apply()
|
||||
return super(LineEdit, self).focusOutEvent(event)
|
||||
|
||||
def apply(self):
|
||||
if self._value != self.value():
|
||||
self.valueSet.emit(self.value())
|
||||
self._value = self.value()
|
||||
|
||||
def value(self):
|
||||
if self.text() == '':
|
||||
return None
|
||||
return float(self.text().replace(',', '.'))
|
||||
|
||||
|
||||
class TextEdit(LineEdit):
|
||||
VALIDATOR_CLS = None
|
||||
valueSet = QtCore.Signal(str)
|
||||
|
||||
def value(self):
|
||||
if self.text() == '':
|
||||
return None
|
||||
return self.text()
|
||||
|
||||
|
||||
class NumEdit(LineEdit):
|
||||
valueSet = QtCore.Signal(float)
|
||||
VALIDATOR_CLS = QtGui.QDoubleValidator
|
||||
|
||||
def __init__(self, minimum=None, maximum=None, parent=None):
|
||||
super(NumEdit, self).__init__(parent)
|
||||
self.dragging = False
|
||||
self.init_mouse_pos = QtCore.QPoint()
|
||||
self.last_mouse_pos = QtCore.QPoint()
|
||||
|
||||
self.minimum = minimum
|
||||
self.maximum = maximum
|
||||
# Minimum horizontal pixels to move before adjusting value
|
||||
self.drag_threshold = 15
|
||||
|
||||
self.setMouseTracking(True)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() != QtCore.Qt.MiddleButton:
|
||||
return super(NumEdit, self).mousePressEvent(event)
|
||||
|
||||
self.setStyleSheet("background-color: #5285A6;")
|
||||
self.clearFocus()
|
||||
self.dragging = True
|
||||
self.init_mouse_pos = event.globalPos()
|
||||
self.last_mouse_pos = event.globalPos()
|
||||
event.accept()
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if not self.dragging:
|
||||
return super(NumEdit, self).mouseMoveEvent(event)
|
||||
|
||||
delta = event.globalPos() - self.last_mouse_pos
|
||||
self.last_mouse_pos = event.globalPos()
|
||||
|
||||
delta_threshold = abs(
|
||||
self.init_mouse_pos.x() - self.last_mouse_pos.x())
|
||||
if self.drag_threshold:
|
||||
if delta_threshold < self.drag_threshold:
|
||||
return
|
||||
self.drag_threshold = False
|
||||
|
||||
self.setStyleSheet("")
|
||||
current_value = float(self.text()) if self.text() else 0.0
|
||||
|
||||
is_integer = self.VALIDATOR_CLS == QtGui.QIntValidator
|
||||
step = 1 if is_integer else 0.1
|
||||
adjustment = delta.x() * step
|
||||
new_value = current_value + adjustment
|
||||
|
||||
if self.validator:
|
||||
min_val, max_val = self.validator.bottom(), self.validator.top()
|
||||
new_value = max(min_val, min(new_value, max_val))
|
||||
|
||||
if is_integer:
|
||||
self.setText(str(int(new_value)))
|
||||
else:
|
||||
self.setText("{0:.2f}".format(new_value))
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
self.drag_threshold = 15
|
||||
self.setStyleSheet("")
|
||||
if event.button() != QtCore.Qt.MiddleButton:
|
||||
return super(NumEdit, self).mouseReleaseEvent(event)
|
||||
|
||||
self.dragging = False
|
||||
event.accept()
|
||||
self.emit_value()
|
||||
self.clearFocus()
|
||||
|
||||
def emit_value(self):
|
||||
current_value = self.value()
|
||||
if current_value is not None:
|
||||
self.valueSet.emit(current_value)
|
||||
|
||||
def value(self):
|
||||
if self.text() == '':
|
||||
return None
|
||||
return float(self.text().replace(',', '.'))
|
||||
|
||||
def enterEvent(self, event):
|
||||
if not self.hasFocus():
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.SplitHCursor)
|
||||
super(NumEdit, self).enterEvent(event)
|
||||
|
||||
def leaveEvent(self, event):
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
super(NumEdit, self).leaveEvent(event)
|
||||
|
||||
def focusInEvent(self, event):
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
super(NumEdit, self).focusInEvent(event)
|
||||
|
||||
def focusOutEvent(self, event):
|
||||
if self.underMouse():
|
||||
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.SplitHCursor)
|
||||
super(NumEdit, self).focusOutEvent(event)
|
||||
|
||||
|
||||
class FloatEdit(NumEdit):
|
||||
valueSet = QtCore.Signal(float)
|
||||
VALIDATOR_CLS = QtGui.QDoubleValidator
|
||||
|
||||
def __init__(self, maximum=None, minimum=None, decimals=2, parent=None):
|
||||
super(FloatEdit, self).__init__(maximum, minimum, parent)
|
||||
|
||||
if minimum is None and maximum is None:
|
||||
self.validator = None
|
||||
else:
|
||||
# using sys.maxsize creates an overflow error, float('inf') is not
|
||||
# sipported by python 2
|
||||
maximum = 999999999. if maximum is None else maximum
|
||||
self.validator = self.VALIDATOR_CLS(
|
||||
minimum, maximum, decimals, self)
|
||||
self.setValidator(self.validator)
|
||||
|
||||
|
||||
class IntEdit(NumEdit):
|
||||
valueSet = QtCore.Signal(int)
|
||||
VALIDATOR_CLS = QtGui.QIntValidator
|
||||
|
||||
def __init__(self, maximum=None, minimum=None, parent=None):
|
||||
super(IntEdit, self).__init__(maximum, minimum, parent)
|
||||
|
||||
if minimum is None and maximum is None:
|
||||
self.validator = None
|
||||
else:
|
||||
# using sys.maxsize creates an overflow error.
|
||||
maximum = 999999999 if maximum is None else maximum
|
||||
self.validator = self.VALIDATOR_CLS(minimum, maximum, self)
|
||||
self.setValidator(self.validator)
|
||||
|
||||
def value(self):
|
||||
if self.text() == '':
|
||||
return None
|
||||
return int(float(self.text()))
|
||||
|
||||
|
||||
class Title(QtWidgets.QLabel):
|
||||
def __init__(self, title, parent=None):
|
||||
super(Title, self).__init__(parent)
|
||||
self.setFixedHeight(20)
|
||||
self.setStyleSheet('background: rgb(0, 0, 0, 25)')
|
||||
self.setText('<b> ' + title)
|
||||
|
||||
|
||||
class TouchEdit(QtWidgets.QLineEdit):
|
||||
def keyPressEvent(self, event):
|
||||
self.setText(QtGui.QKeySequence(event.key()).toString().lower())
|
||||
self.textEdited.emit(self.text())
|
||||
|
||||
|
||||
class CommandButton(QtWidgets.QWidget):
|
||||
released = QtCore.Signal()
|
||||
playReleased = QtCore.Signal()
|
||||
|
||||
def __init__(self, label, parent=None):
|
||||
super(CommandButton, self).__init__(parent)
|
||||
self.mainbutton = QtWidgets.QPushButton(label)
|
||||
self.mainbutton.released.connect(self.released.emit)
|
||||
self.playbutton = QtWidgets.QPushButton(icon('play.png'), '')
|
||||
self.playbutton.released.connect(self.playReleased.emit)
|
||||
self.playbutton.setFixedSize(22, 22)
|
||||
self.layout = QtWidgets.QHBoxLayout(self)
|
||||
self.layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.layout.setSpacing(2)
|
||||
self.layout.addWidget(self.mainbutton)
|
||||
self.layout.addWidget(self.playbutton)
|
||||
|
||||
|
||||
class LayerEdit(QtWidgets.QWidget):
|
||||
valueSet = QtCore.Signal(object)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super(LayerEdit, self).__init__(parent)
|
||||
self.layer = QtWidgets.QLineEdit()
|
||||
self.layer.setReadOnly(True)
|
||||
self.reset = QtWidgets.QPushButton('x')
|
||||
self.reset.released.connect(self.do_reset)
|
||||
|
||||
self.layout = QtWidgets.QHBoxLayout(self)
|
||||
self.layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.layout.setSpacing(0)
|
||||
self.layout.addWidget(self.layer)
|
||||
self.layout.addWidget(self.reset)
|
||||
|
||||
def set_layer(self, text):
|
||||
self.layer.setText(text or '')
|
||||
|
||||
def do_reset(self):
|
||||
if not self.layer.text():
|
||||
return
|
||||
self.layer.setText('')
|
||||
self.valueSet.emit(None)
|
||||
|
||||
|
||||
class ZoomsLockedEditor(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, document, parent=None):
|
||||
super(ZoomsLockedEditor, self).__init__(parent)
|
||||
self.model = ZoomLockedModel(document)
|
||||
|
||||
self.table = QtWidgets.QTableView()
|
||||
self.table.setEditTriggers(QtWidgets.QAbstractItemView.AllEditTriggers)
|
||||
self.table.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
||||
mode = QtWidgets.QHeaderView.ResizeToContents
|
||||
self.table.horizontalHeader().setSectionResizeMode(mode)
|
||||
self.table.setFixedHeight(120)
|
||||
self.table.setItemDelegateForColumn(0, CheckDelegate())
|
||||
self.table.setModel(self.model)
|
||||
|
||||
layout = QtWidgets.QHBoxLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.addWidget(self.table)
|
||||
|
||||
|
||||
class ZoomLockedModel(QtCore.QAbstractTableModel):
|
||||
HEADERS = 'Z-lock', 'BG Color', 'Name'
|
||||
|
||||
def __init__(self, document, parent=None):
|
||||
super(ZoomLockedModel, self).__init__(parent)
|
||||
self.document = document
|
||||
self.document.changed.connect(self.layoutChanged.emit)
|
||||
|
||||
def columnCount(self, _):
|
||||
return 3
|
||||
|
||||
def rowCount(self, _):
|
||||
return count_panels(self.document.data['general']['panels'])
|
||||
|
||||
def flags(self, _):
|
||||
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsEditable
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
if role != QtCore.Qt.DisplayRole:
|
||||
return
|
||||
if orientation == QtCore.Qt.Vertical:
|
||||
return str(section + 1)
|
||||
return self.HEADERS[section]
|
||||
|
||||
def set_zoom_locked(self, row, state):
|
||||
self.layoutAboutToBeChanged.emit()
|
||||
self.document.data['general']['panels.zoom_locked'][row] = state
|
||||
self.document.general_option_changed.emit(
|
||||
'attribute_editor', 'panels.zoom_locked')
|
||||
self.document.record_undo()
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def setData(self, index, value, role):
|
||||
if index.column() == 0:
|
||||
return False
|
||||
|
||||
if index.column() == 1 and role == QtCore.Qt.EditRole:
|
||||
if value and not QtGui.QColor(value).isValid():
|
||||
if QtGui.QColor('#' + value).isValid():
|
||||
value = '#' + value
|
||||
else:
|
||||
return False
|
||||
value = value or None
|
||||
self.document.data['general']['panels.colors'][index.row()] = value
|
||||
self.document.general_option_changed.emit(
|
||||
'attribute_editor', 'panels.colors')
|
||||
self.document.record_undo()
|
||||
return True
|
||||
|
||||
if index.column() == 2 and role == QtCore.Qt.EditRole:
|
||||
self.document.data['general']['panels.names'][index.row()] = value
|
||||
self.document.general_option_changed.emit(
|
||||
'attribute_editor', 'panels.names')
|
||||
self.document.record_undo()
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def data(self, index, role):
|
||||
if not index.isValid():
|
||||
return
|
||||
|
||||
general = self.document.data['general']
|
||||
if role == QtCore.Qt.DecorationRole:
|
||||
if index.column() == 1:
|
||||
color = general['panels.colors'][index.row()]
|
||||
return get_color_icon(color)
|
||||
|
||||
if role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
|
||||
if index.column() == 1:
|
||||
color = general['panels.colors'][index.row()]
|
||||
return str(color) if color else ''
|
||||
if index.column() == 2:
|
||||
return str(general['panels.names'][index.row()])
|
||||
|
||||
|
||||
# @lru_cache()
|
||||
def get_color_icon(color, size=None):
|
||||
px = QtGui.QPixmap(QtCore.QSize(*(size if size else (64, 64))))
|
||||
px.fill(QtCore.Qt.transparent)
|
||||
rect = QtCore.QRectF(0, 0, px.size().width(), px.size().height())
|
||||
painter = QtGui.QPainter(px)
|
||||
try:
|
||||
if not color:
|
||||
painter.drawRect(rect)
|
||||
font = QtGui.QFont()
|
||||
font.setPixelSize(50)
|
||||
option = QtGui.QTextOption()
|
||||
option.setAlignment(QtCore.Qt.AlignCenter)
|
||||
painter.setPen(QtGui.QPen(QtGui.QColor('#ddd')))
|
||||
painter.setFont(font)
|
||||
painter.drawText(grow_rect(rect, 300), X, option)
|
||||
painter.end()
|
||||
return QtGui.QIcon(px)
|
||||
|
||||
painter.setPen(QtCore.Qt.NoPen)
|
||||
painter.setBrush(QtGui.QColor(color))
|
||||
painter.drawRect(rect)
|
||||
painter.end()
|
||||
return QtGui.QIcon(px)
|
||||
|
||||
except BaseException:
|
||||
import traceback
|
||||
print(traceback.format_exc())
|
||||
painter.end()
|
||||
return QtGui.QIcon()
|
||||
|
||||
|
||||
class CheckDelegate(QtWidgets.QItemDelegate):
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if event.button() != QtCore.Qt.LeftButton:
|
||||
return
|
||||
self.update()
|
||||
|
||||
def createEditor(self, parent, _, index):
|
||||
model = index.model()
|
||||
general = model.document.data['general']
|
||||
state = general['panels.zoom_locked'][index.row()]
|
||||
model.set_zoom_locked(index.row(), not state)
|
||||
checker = CheckWidget(not state, parent)
|
||||
checker.toggled.connect(partial(model.set_zoom_locked, index.row()))
|
||||
return checker
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
model = index.model()
|
||||
general = model.document.data['general']
|
||||
state = general['panels.zoom_locked'][index.row()]
|
||||
|
||||
center = option.rect.center()
|
||||
painter.setBrush(QtCore.Qt.NoBrush)
|
||||
rect = QtCore.QRectF(center.x() - 10, center.y() - 10, 20, 20)
|
||||
if not state:
|
||||
return
|
||||
font = QtGui.QFont()
|
||||
font.setPixelSize(20)
|
||||
option = QtGui.QTextOption()
|
||||
option.setAlignment(QtCore.Qt.AlignCenter)
|
||||
painter.drawText(rect, V, option)
|
||||
|
||||
|
||||
class CheckWidget(QtWidgets.QWidget):
|
||||
toggled = QtCore.Signal(bool)
|
||||
|
||||
def __init__(self, state, parent=None):
|
||||
super(CheckWidget, self).__init__(parent)
|
||||
self.state = state
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
if event.button() == QtCore.Qt.LeftButton:
|
||||
self.state = not self.state
|
||||
self.toggled.emit(self.state)
|
||||
self.update()
|
||||
|
||||
def paintEvent(self, _):
|
||||
painter = QtGui.QPainter(self)
|
||||
center = self.rect().center()
|
||||
painter.setBrush(QtCore.Qt.NoBrush)
|
||||
rect = QtCore.QRectF(center.x() - 15, center.y() - 15, 30, 30)
|
||||
painter.drawRect(rect)
|
||||
if not self.state:
|
||||
return
|
||||
font = QtGui.QFont()
|
||||
font.setPixelSize(20)
|
||||
option = QtGui.QTextOption()
|
||||
option.setAlignment(QtCore.Qt.AlignCenter)
|
||||
painter.drawText(rect, V, option)
|
||||
|
||||
|
||||
class ChildrenWidget(QtWidgets.QWidget):
|
||||
children_changed = QtCore.Signal(list)
|
||||
|
||||
def __init__(self, document, display_options, parent=None):
|
||||
super(ChildrenWidget, self).__init__(parent)
|
||||
self.display_options = display_options
|
||||
self.model = ChildrenModel(document)
|
||||
self.list = QtWidgets.QListView()
|
||||
self.list.setModel(self.model)
|
||||
self.list.selectionModel().selectionChanged.connect(
|
||||
self.hightlight_children)
|
||||
mode = QtWidgets.QAbstractItemView.ExtendedSelection
|
||||
self.list.setSelectionMode(mode)
|
||||
self.delete = QtWidgets.QPushButton('Delete')
|
||||
self.delete.released.connect(self.call_delete)
|
||||
|
||||
layout = QtWidgets.QVBoxLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.addWidget(self.list)
|
||||
layout.addWidget(self.delete)
|
||||
|
||||
def hightlight_children(self, *_):
|
||||
indexes = self.list.selectedIndexes()
|
||||
ids = [self.model.data(i, QtCore.Qt.DisplayRole) for i in indexes]
|
||||
self.display_options.highlighted_children_ids = ids
|
||||
self.display_options.options_changed.emit()
|
||||
|
||||
def clear(self):
|
||||
self.model.layoutAboutToBeChanged.emit()
|
||||
self.display_options.highlighted_children_ids = []
|
||||
self.list.selectionModel().clear()
|
||||
self.model.children = []
|
||||
self.model.layoutChanged.emit()
|
||||
|
||||
def call_delete(self):
|
||||
indexes = self.list.selectedIndexes()
|
||||
indexes = sorted(indexes, key=lambda i: i.row(), reverse=True)
|
||||
self.model.layoutAboutToBeChanged.emit()
|
||||
for index in indexes:
|
||||
self.model.children.pop(index.row())
|
||||
self.model.layoutChanged.emit()
|
||||
self.display_options.highlighted_children_ids = []
|
||||
self.display_options.options_changed.emit()
|
||||
self.children_changed.emit(self.model.children[:])
|
||||
|
||||
def set_children(self, children):
|
||||
self.model.layoutAboutToBeChanged.emit()
|
||||
self.model.children = children[:]
|
||||
self.model.layoutChanged.emit()
|
||||
|
||||
|
||||
class ChildrenModel(QtCore.QAbstractListModel):
|
||||
def __init__(self, document, parent=None):
|
||||
super(ChildrenModel, self).__init__(parent)
|
||||
self.document = document
|
||||
self.children = []
|
||||
|
||||
def rowCount(self, _):
|
||||
return len(self.children)
|
||||
|
||||
def data(self, index, role):
|
||||
id_ = self.children[index.row()]
|
||||
if role == QtCore.Qt.DisplayRole:
|
||||
return id_
|
||||
|
||||
if id_ in self.document.shapes_by_id:
|
||||
return
|
||||
|
||||
if role == QtCore.Qt.BackgroundRole:
|
||||
brush = QtGui.QBrush(QtGui.QColor('#555555'))
|
||||
brush.setStyle(QtCore.Qt.BDiagPattern)
|
||||
return brush
|
||||
|
||||
if role == QtCore.Qt.FontRole:
|
||||
font = QtGui.QFont()
|
||||
font.setStrikeOut(True)
|
||||
font.setItalic(True)
|
||||
return font
|
||||
|
||||
if role == QtCore.Qt.TextColorRole:
|
||||
return QtGui.QColor('#999999')
|
||||
Reference in New Issue
Block a user