1#!/usr/local/bin/python3.8 2# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai 3 4 5__license__ = 'GPL v3' 6__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' 7__docformat__ = 'restructuredtext en' 8 9 10from qt.core import ( 11 QToolButton, QSize, QPropertyAnimation, Qt, QMetaObject, pyqtProperty, QSizePolicy, 12 QWidget, QIcon, QPainter, QStyleOptionToolButton, QStyle, QAbstractAnimation) 13 14from calibre.gui2 import config 15 16 17class ThrobbingButton(QToolButton): 18 19 @pyqtProperty(int) 20 def icon_size(self): 21 return self._icon_size 22 23 @icon_size.setter 24 def icon_size(self, value): 25 self._icon_size = value 26 27 def __init__(self, *args): 28 QToolButton.__init__(self, *args) 29 # vertically size policy must be expanding for it to align inside a 30 # toolbar 31 self.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Expanding) 32 self._icon_size = -1 33 QToolButton.setIcon(self, QIcon(I('donate.png'))) 34 self.setText('\xa0') 35 self.animation = QPropertyAnimation(self, b'icon_size', self) 36 self.animation.setDuration(int(60/72.*1000)) 37 self.animation.setLoopCount(4) 38 self.animation.valueChanged.connect(self.value_changed) 39 self.setCursor(Qt.CursorShape.PointingHandCursor) 40 self.animation.finished.connect(self.animation_finished) 41 42 def animation_finished(self): 43 self.icon_size = self.iconSize().width() 44 45 def enterEvent(self, ev): 46 self.start_animation() 47 48 def leaveEvent(self, ev): 49 self.stop_animation() 50 51 def value_changed(self, val): 52 self.update() 53 54 def start_animation(self): 55 if config['disable_animations']: 56 return 57 if self.animation.state() != QAbstractAnimation.State.Stopped or not self.isVisible(): 58 return 59 size = self.iconSize().width() 60 smaller = int(0.7 * size) 61 self.animation.setStartValue(smaller) 62 self.animation.setEndValue(size) 63 QMetaObject.invokeMethod(self.animation, 'start', Qt.ConnectionType.QueuedConnection) 64 65 def stop_animation(self): 66 self.animation.stop() 67 self.animation_finished() 68 69 def paintEvent(self, ev): 70 size = self._icon_size if self._icon_size > 10 else self.iconSize().width() 71 p = QPainter(self) 72 opt = QStyleOptionToolButton() 73 self.initStyleOption(opt) 74 s = self.style() 75 opt.iconSize = QSize(size, size) 76 s.drawComplexControl(QStyle.ComplexControl.CC_ToolButton, opt, p, self) 77 78 79if __name__ == '__main__': 80 from qt.core import QApplication, QHBoxLayout 81 app = QApplication([]) 82 w = QWidget() 83 w.setLayout(QHBoxLayout()) 84 b = ThrobbingButton() 85 b.setIcon(QIcon(I('donate.png'))) 86 w.layout().addWidget(b) 87 w.show() 88 b.set_normal_icon_size(64, 64) 89 b.start_animation() 90 91 app.exec() 92