From 1fe9ff0af78a7a91c67997373a3b86946de5cff1 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 3 May 2020 12:45:58 +0200 Subject: [PATCH] Updated the switch class to match code standard --- nw/additions/qswitch.py | 248 ++++++++++++++++++++------------------ nw/constants/constants.py | 4 + 2 files changed, 136 insertions(+), 116 deletions(-) diff --git a/nw/additions/qswitch.py b/nw/additions/qswitch.py index b7d3fdcd..b25e99eb 100644 --- a/nw/additions/qswitch.py +++ b/nw/additions/qswitch.py @@ -35,72 +35,74 @@ import logging import nw -from PyQt5.QtCore import QPropertyAnimation, QRectF, QSize, Qt, pyqtProperty +from PyQt5.QtCore import Qt, QSize, QRectF, QPropertyAnimation, pyqtProperty +from PyQt5.QtWidgets import QAbstractButton, QSizePolicy from PyQt5.QtGui import QPainter -from PyQt5.QtWidgets import ( - QAbstractButton, - QApplication, - QHBoxLayout, - QSizePolicy, - QWidget, -) + +from nw.constants import nwUnicode logger = logging.getLogger(__name__) -class Switch(QAbstractButton): - def __init__(self, parent=None, track_radius=10, thumb_radius=8): +class QSwitch(QAbstractButton): + + def __init__(self, parent=None): super().__init__(parent=parent) + self.setCheckable(True) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) - self._track_radius = track_radius - self._thumb_radius = thumb_radius + self._trackRadius = 10 + self._thumbRadius = 8 - self._margin = max(0, self._thumb_radius - self._track_radius) - self._base_offset = max(self._thumb_radius, self._track_radius) - self._end_offset = { - True: lambda: self.width() - self._base_offset, - False: lambda: self._base_offset, + self._margin = max(0, self._thumbRadius - self._trackRadius) + self._baseOffset = max(self._thumbRadius, self._trackRadius) + self._endOffset = { + True: lambda: self.width() - self._baseOffset, + False: lambda: self._baseOffset, } - self._offset = self._base_offset + self._offset = self._baseOffset palette = self.palette() - if self._thumb_radius > self._track_radius: - self._track_color = { + if self._thumbRadius > self._trackRadius: + self._trackColor = { True: palette.highlight(), False: palette.dark(), } - self._thumb_color = { + self._thumbColor = { True: palette.highlight(), False: palette.light(), } - self._text_color = { + self._textColor = { True: palette.highlightedText().color(), False: palette.dark().color(), } - self._thumb_text = { + self._thumbText = { True: '', False: '', } - self._track_opacity = 0.5 + self._trackOpacity = 0.5 else: - self._thumb_color = { + self._thumbColor = { True: palette.highlightedText(), False: palette.light(), } - self._track_color = { + self._trackColor = { True: palette.highlight(), False: palette.dark(), } - self._text_color = { + self._textColor = { True: palette.highlight().color(), False: palette.dark().color(), } - self._thumb_text = { - True: '✔', - False: '✕', + self._thumbText = { + True: nwUnicode.U_CHECK, + False: nwUnicode.U_MULT, } - self._track_opacity = 1 + self._trackOpacity = 1 + + ## + # Properties + ## @pyqtProperty(int) def offset(self): @@ -110,114 +112,128 @@ class Switch(QAbstractButton): def offset(self, value): self._offset = value self.update() + return - def sizeHint(self): # pylint: disable=invalid-name - return QSize( - 4 * self._track_radius + 2 * self._margin, - 2 * self._track_radius + 2 * self._margin, - ) + ## + # Getters and Setters + ## + + def trackRadius(self): + return self._trackRadius + + def setTrackRadius(self, theValue): + if isinstance(theValue, int): + if theValue > 0: + self._trackRadius = theValue + return + raise ValueError("trackRadius must be an integer > 0") + self.update() + return + + def thumbRadius(self): + return self._thumbRadius + + def setThumbRadius(self, theValue): + if isinstance(theValue, int): + if theValue > 0: + self._thumbRadius = theValue + return + raise ValueError("thumbRadius must be an integer > 0") + self.update() + return def setChecked(self, checked): super().setChecked(checked) - self.offset = self._end_offset[checked]() + self.offset = self._endOffset[checked]() + + def sizeHint(self): + return QSize( + 4 * self._trackRadius + 2 * self._margin, + 2 * self._trackRadius + 2 * self._margin, + ) + + ## + # Events + ## def resizeEvent(self, event): + """Overload resize to ensure correct offset. + """ super().resizeEvent(event) - self.offset = self._end_offset[self.isChecked()]() + self.offset = self._endOffset[self.isChecked()]() + return - def paintEvent(self, event): # pylint: disable=invalid-name, unused-argument - p = QPainter(self) - p.setRenderHint(QPainter.Antialiasing, True) - p.setPen(Qt.NoPen) - track_opacity = self._track_opacity - thumb_opacity = 1.0 - text_opacity = 1.0 + def paintEvent(self, event): + """Drawing the switch itself. + """ + qPaint = QPainter(self) + qPaint.setRenderHint(QPainter.Antialiasing, True) + qPaint.setPen(Qt.NoPen) + trackOpacity = self._trackOpacity + thumbOpacity = 1.0 + textOpacity = 1.0 if self.isEnabled(): - track_brush = self._track_color[self.isChecked()] - thumb_brush = self._thumb_color[self.isChecked()] - text_color = self._text_color[self.isChecked()] + trackBrush = self._trackColor[self.isChecked()] + thumbBrush = self._thumbColor[self.isChecked()] + textColor = self._textColor[self.isChecked()] else: - track_opacity *= 0.8 - track_brush = self.palette().shadow() - thumb_brush = self.palette().mid() - text_color = self.palette().shadow().color() + trackOpacity *= 0.8 + trackBrush = self.palette().shadow() + thumbBrush = self.palette().mid() + textColor = self.palette().shadow().color() - p.setBrush(track_brush) - p.setOpacity(track_opacity) - p.drawRoundedRect( + qPaint.setBrush(trackBrush) + qPaint.setOpacity(trackOpacity) + qPaint.drawRoundedRect( self._margin, self._margin, - self.width() - 2 * self._margin, - self.height() - 2 * self._margin, - self._track_radius, - self._track_radius, + self.width() - 2*self._margin, + self.height() - 2*self._margin, + self._trackRadius, + self._trackRadius, ) - p.setBrush(thumb_brush) - p.setOpacity(thumb_opacity) - p.drawEllipse( - self.offset - self._thumb_radius, - self._base_offset - self._thumb_radius, - 2 * self._thumb_radius, - 2 * self._thumb_radius, + qPaint.setBrush(thumbBrush) + qPaint.setOpacity(thumbOpacity) + qPaint.drawEllipse( + self.offset - self._thumbRadius, + self._baseOffset - self._thumbRadius, + 2*self._thumbRadius, + 2*self._thumbRadius, ) - p.setPen(text_color) - p.setOpacity(text_opacity) - font = p.font() - font.setPixelSize(1.5 * self._thumb_radius) - p.setFont(font) - p.drawText( + qPaint.setPen(textColor) + qPaint.setOpacity(textOpacity) + theFont = qPaint.font() + theFont.setPixelSize(1.5*self._thumbRadius) + qPaint.setFont(theFont) + qPaint.drawText( QRectF( - self.offset - self._thumb_radius, - self._base_offset - self._thumb_radius, - 2 * self._thumb_radius, - 2 * self._thumb_radius, + self.offset - self._thumbRadius, + self._baseOffset - self._thumbRadius, + 2*self._thumbRadius, + 2*self._thumbRadius, ), Qt.AlignCenter, - self._thumb_text[self.isChecked()], + self._thumbText[self.isChecked()], ) + return - def mouseReleaseEvent(self, event): # pylint: disable=invalid-name + def mouseReleaseEvent(self, event): + """Animate the switch. + """ super().mouseReleaseEvent(event) if event.button() == Qt.LeftButton: - anim = QPropertyAnimation(self, b'offset', self) - anim.setDuration(120) - anim.setStartValue(self.offset) - anim.setEndValue(self._end_offset[self.isChecked()]()) - anim.start() + doAnim = QPropertyAnimation(self, b'offset', self) + doAnim.setDuration(120) + doAnim.setStartValue(self.offset) + doAnim.setEndValue(self._endOffset[self.isChecked()]()) + doAnim.start() + return - def enterEvent(self, event): # pylint: disable=invalid-name + def enterEvent(self, event): + """Change the cursor when hovering the button. + """ self.setCursor(Qt.PointingHandCursor) super().enterEvent(event) + return - -# def main(): -# app = QApplication([]) - -# # Thumb size < track size (Gitlab style) -# s1 = Switch() -# s1.toggled.connect(lambda c: print('toggled', c)) -# s1.clicked.connect(lambda c: print('clicked', c)) -# s1.pressed.connect(lambda: print('pressed')) -# s1.released.connect(lambda: print('released')) -# s2 = Switch() -# s2.setEnabled(False) - -# # Thumb size > track size (Android style) -# s3 = Switch(thumb_radius=11, track_radius=8) -# s4 = Switch(thumb_radius=11, track_radius=8) -# s4.setEnabled(False) - -# l = QHBoxLayout() -# l.addWidget(s1) -# l.addWidget(s2) -# l.addWidget(s3) -# l.addWidget(s4) -# w = QWidget() -# w.setLayout(l) -# w.show() - -# app.exec() - - -# if __name__ == '__main__': -# main() +# END Class QSwitch diff --git a/nw/constants/constants.py b/nw/constants/constants.py index 3f6192d4..fe327525 100644 --- a/nw/constants/constants.py +++ b/nw/constants/constants.py @@ -233,6 +233,8 @@ class nwUnicode: ## Other U_NBSP = "\u00a0" # Non-breaking space U_PARA = "\u2029" # Paragraph separator + U_CHECK = "\u2714" # Heavy check mark + U_MULT = "\u2715" # Multiplication x ## Arrows U_UTRI = "\u2bc5" # Up-pointing triangle @@ -270,6 +272,8 @@ class nwUnicode: ## Other H_NBSP = " " + H_CHECK = "✔" + H_MULT = "✕" ## Arrows H_UTRI = "⯅"