diff options
Diffstat (limited to 'raphodo/rotatedpushbutton.py')
-rw-r--r-- | raphodo/rotatedpushbutton.py | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/raphodo/rotatedpushbutton.py b/raphodo/rotatedpushbutton.py new file mode 100644 index 0000000..d80d088 --- /dev/null +++ b/raphodo/rotatedpushbutton.py @@ -0,0 +1,175 @@ +# Copyright (C) 2015-2016 Damon Lynch <damonlynch@gmail.com> + +# This file is part of Rapid Photo Downloader. +# +# Rapid Photo Downloader is free software: you can redistribute it and/or +# modify it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Rapid Photo Downloader is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Rapid Photo Downloader. If not, +# see <http://www.gnu.org/licenses/>. + +__author__ = 'Damon Lynch' +__copyright__ = "Copyright 2015-2016, Damon Lynch" + +from enum import IntEnum + +from PyQt5.QtGui import (QColor, QPalette) +from PyQt5.QtWidgets import (QPushButton, QStylePainter, QStyle, QStyleOptionButton, QHBoxLayout) + +class VerticalRotation(IntEnum): + left_side = 270 + right_side = 90 + +class FlatButton: + _padding = 'padding-left: {padding_side}px; padding-right: {padding_side}px; padding-top: ' \ + '{padding_top}px; padding-bottom: {padding_bottom}px;'.format( + padding_top=6, padding_side=7, padding_bottom=6) + + def setFlatStyle(self, button: QPushButton, + darker_if_checked: bool=True, + padding: str='', + color: QColor=None, + text_color: QColor=None) -> None: + if color is None: + color = QPalette().color(QPalette.Background) + default_color = color.name(QColor.HexRgb) + + if darker_if_checked: + checked_color = color.darker(125).name(QColor.HexRgb) + else: + checked_color = default_color + + hover_color = color.darker(110).name(QColor.HexRgb) + + if not padding: + padding = self._padding + + if text_color is not None: + text = 'color: {};'.format(text_color.name(QColor.HexRgb)) + else: + text = '' + + # outline:none is used to remove the rectangle that appears on a + # button when the button has focus + # http://stackoverflow.com/questions/17280056/qt-css-decoration-on-focus + stylesheet = """ + QPushButton { background-color: %s; + border: 0px; + outline: none; + %s + %s} + QPushButton:checked { background-color: %s; border: none; } + QPushButton:hover{ background-color: %s; border-style: inset; } + """ % (default_color, padding, text, checked_color, hover_color) # + + button.setStyleSheet(stylesheet) + + def setHighlightedFlatStyle(self, button: QPushButton) -> None: + palette = QPalette() + color = palette.color(palette.Highlight) + text_color = palette.color(palette.HighlightedText) + self.setFlatStyle(button, color=color, text_color=text_color, darker_if_checked=False) + +class RotatedButton(QPushButton, FlatButton): + leftSide = 270.0 + rightSide = 90.0 + + def __init__(self, text: str, + rotation: float, + flat: bool=True, + use_highlight_color=False, + checkable: bool=True, + parent=None) -> None: + """ + A push button to show in the left or right side of a window + :param text: text to display + :param rotation: whether on the left or right side of the window + :param flat: if True, set style to flat style + :param use_highlight_color: if True, the button's color should be the palette's color + for highlighting selected items. Takes effect only when using a flat is also True. + :param checkable: if the button is checkable or not + :param parent: optional parent widget + """ + + super().__init__(text, parent) + self.buttonRotation = rotation + if flat: + # Use only the stylesheet to give the appearance of being flat. + # Don't mix and match stylesheet and non-stylesheet options for widgets. + # http://stackoverflow.com/questions/34654545/qt-flat-qpushbutton-background-color-doesnt-work + if use_highlight_color: + self.setHighlightedFlatStyle(self) + else: + self.setFlatStyle(self) + self.setCheckable(checkable) + + def paintEvent(self, event): + painter = QStylePainter(self) + painter.rotate(self.buttonRotation) + if self.buttonRotation == VerticalRotation.left_side: + painter.translate(-1 * self.height(), 0) + elif self.buttonRotation == VerticalRotation.right_side: + painter.translate(0, -1 * self.width()) + painter.drawControl(QStyle.CE_PushButton, self.getSyleOptions()) + + def setRotation(self, rotation: float): + self.buttonRotation = rotation + + def sizeHint(self): + size = super().sizeHint() + size.transpose() + return size + + def getSyleOptions(self) -> QStyleOptionButton: + options = QStyleOptionButton() + options.initFrom(self) + size = options.rect.size() + size.transpose() + options.rect.setSize(size) + + try: + options.features = QStyleOptionButton.None_ + except AttributeError: + # Allow for bug in PyQt 5.4 + options.features = getattr(QStyleOptionButton, 'None') + if self.isFlat(): + options.features |= QStyleOptionButton.Flat + if self.menu(): + options.features |= QStyleOptionButton.HasMenu + if self.autoDefault() or self.isDefault(): + options.features |= QStyleOptionButton.AutoDefaultButton + if self.isDefault(): + options.features |= QStyleOptionButton.DefaultButton + if self.isDown() or (self.menu() and self.menu().isVisible()): + options.state |= QStyle.State_Sunken + if self.isChecked(): + options.state |= QStyle.State_On + if not self.isFlat() and not self.isDown(): + options.state |= QStyle.State_Raised + + options.text = self.text() + options.icon = self.icon() + options.iconSize = self.iconSize() + return options + + def setHighlighted(self, highlighted: bool) -> None: + if highlighted: + self.setHighlightedFlatStyle(self) + else: + self.setFlatStyle(self) + self.update() + + + + + + + |