"""
Very basic components used by other widgets.
These are relatively sparsely documented because their operation is mostly self-explanatory
"""
import copy
import pdb
import typing
import numpy as np
from PySide2 import QtWidgets, QtCore, QtGui
from pvp.gui import styles, mono_font
[docs]class DoubleSlider(QtWidgets.QSlider):
"""
Slider capable of representing floats
Ripped off from
and https://stackoverflow.com/a/50300848 ,
Thank you!!!
"""
# override the default valueChanged signal
doubleValueChanged = QtCore.Signal(float)
def __init__(self, decimals=1, *args, **kargs):
super(DoubleSlider, self).__init__(*args, **kargs)
self._multi = 10 ** decimals
self.decimals = decimals
self.valueChanged.connect(self.emitDoubleValueChanged)
[docs] def setDecimals(self, decimals):
self._multi = 10 ** decimals
[docs] def emitDoubleValueChanged(self):
self.doubleValueChanged.emit(self.value())
[docs] def value(self):
return float(super(DoubleSlider, self).value()) / self._multi
[docs] def setMinimum(self, value):
return super(DoubleSlider, self).setMinimum(round(value * self._multi))
[docs] def setMaximum(self, value):
return super(DoubleSlider, self).setMaximum(round(value * self._multi))
[docs] def minimum(self):
return super(DoubleSlider, self).minimum() / self._multi
[docs] def _minimum(self):
return super(DoubleSlider, self).minimum()
[docs] def maximum(self):
return super(DoubleSlider, self).maximum() / self._multi
[docs] def _maximum(self):
return super(DoubleSlider, self).maximum()
[docs] def setSingleStep(self, value):
return super(DoubleSlider, self).setSingleStep(round(value * self._multi))
[docs] def singleStep(self):
return float(super(DoubleSlider, self).singleStep()) / self._multi
[docs] def _singleStep(self):
return super(DoubleSlider, self).singleStep()
[docs] def setValue(self, value):
# pdb.set_trace()
super(DoubleSlider, self).setValue(int(round(value * self._multi)))
[docs]class KeyPressHandler(QtCore.QObject):
"""Custom key press handler
https://gist.github.com/mfessenden/baa2b87b8addb0b60e54a11c1da48046"""
escapePressed = QtCore.Signal(bool)
returnPressed = QtCore.Signal(bool)
[docs] def eventFilter(self, obj, event):
if event.type() == QtCore.QEvent.KeyPress:
event_key = event.key()
if event_key == QtCore.Qt.Key_Escape:
self.escapePressed.emit(True)
return True
if event_key == QtCore.Qt.Key_Return or event_key == QtCore.Qt.Key_Enter:
self.returnPressed.emit(True)
return True
return QtCore.QObject.eventFilter(self, obj, event)
[docs]class EditableLabel(QtWidgets.QWidget):
"""Editable label
https://gist.github.com/mfessenden/baa2b87b8addb0b60e54a11c1da48046"""
textChanged = QtCore.Signal(str)
def __init__(self, parent=None, **kwargs):
super(EditableLabel, self).__init__(parent=parent, **kwargs)
self.is_editable = kwargs.get("editable", True)
self.keyPressHandler = KeyPressHandler(self)
# self.setStyleSheet(styles.CONTROL_VALUE)
self.mainLayout = QtWidgets.QHBoxLayout(self)
self.mainLayout.setContentsMargins(0, 0, 0, 0)
self.mainLayout.setObjectName("mainLayout")
self.label = QtWidgets.QLabel(self)
self.label.setObjectName("label")
# self.label.setStyleSheet(styles.CONTROL_VALUE)
# self.label.setMinimumHeight(styles.VALUE_SIZE)
self.mainLayout.addWidget(self.label)
self.lineEdit = QtWidgets.QLineEdit(self)
# self.setSizePolicy(QtWidgets.QSizePolicy.Maximum,
# QtWidgets.QSizePolicy.Expanding)
# self.lineEdit.setMinimumHeight(styles.VALUE_SIZE)
self.lineEdit.setObjectName("lineEdit")
self.lineEdit.setValidator(QtGui.QDoubleValidator())
self.mainLayout.addWidget(self.lineEdit)
# hide the line edit initially
self.lineEdit.setHidden(True)
# setup signals
self.create_signals()
[docs] def create_signals(self):
self.lineEdit.installEventFilter(self.keyPressHandler)
self.label.mousePressEvent = self.labelPressedEvent
# give the lineEdit both a `returnPressed` and `escapedPressed` action
self.keyPressHandler.escapePressed.connect(self.escapePressedAction)
self.keyPressHandler.returnPressed.connect(self.returnPressedAction)
[docs] def text(self):
"""Standard QLabel text getter"""
return self.label.text()
[docs] def setText(self, text):
"""Standard QLabel text setter"""
self.label.blockSignals(True)
self.label.setText(text)
self.label.blockSignals(False)
[docs] def labelPressedEvent(self, event):
"""Set editable if the left mouse button is clicked"""
if event.button() == QtCore.Qt.MouseButton.LeftButton:
self.setLabelEditableAction()
[docs] def setLabelEditableAction(self):
"""Action to make the widget editable"""
if not self.is_editable:
return
self.label.setHidden(True)
self.label.blockSignals(True)
self.lineEdit.setHidden(False)
self.lineEdit.setText(self.label.text())
self.lineEdit.blockSignals(False)
self.lineEdit.setFocus(QtCore.Qt.MouseFocusReason)
self.lineEdit.selectAll()
[docs] def setEditable(self, editable: bool):
self.is_editable = editable
[docs] def labelUpdatedAction(self):
"""Indicates the widget text has been updated"""
text_to_update = self.lineEdit.text()
if text_to_update != self.label.text():
self.label.setText(text_to_update)
self.textChanged.emit(text_to_update)
self.label.setHidden(False)
self.lineEdit.setHidden(True)
self.lineEdit.blockSignals(True)
self.label.blockSignals(False)
[docs] def returnPressedAction(self):
"""Return/enter event handler"""
self.labelUpdatedAction()
[docs] def escapePressedAction(self):
"""Escape event handler"""
self.label.setHidden(False)
self.lineEdit.setHidden(True)
self.lineEdit.blockSignals(True)
self.label.blockSignals(False)
[docs]class QHLine(QtWidgets.QFrame):
"""
with respct to https://stackoverflow.com/a/51057516
"""
def __init__(self, parent=None, color=styles.DIVIDER_COLOR):
super(QHLine, self).__init__(parent)
self.setFrameShape(QtWidgets.QFrame.HLine)
self.setFrameShadow(QtWidgets.QFrame.Plain)
self.setLineWidth(0)
self.setMidLineWidth(3)
self.setContentsMargins(0, 0, 0, 0)
color = QtGui.QColor(color)
self.setColor(color)
[docs] def setColor(self, color):
pal = self.palette()
pal.setColor(QtGui.QPalette.WindowText, color)
self.setPalette(pal)
[docs]class QVLine(QtWidgets.QFrame):
def __init__(self, parent=None, color=styles.DIVIDER_COLOR):
super(QVLine, self).__init__(parent)
self.setFrameShape(QtWidgets.QFrame.VLine)
self.setFrameShadow(QtWidgets.QFrame.Plain)
self.setLineWidth(0)
self.setMidLineWidth(3)
self.setContentsMargins(0, 0, 0, 0)
color = QtGui.QColor(color)
self.setColor(color)
[docs] def setColor(self, color):
pal = self.palette()
pal.setColor(QtGui.QPalette.WindowText, color)
self.setPalette(pal)