Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pixmapdial.py 11KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Pixmap Dial, a custom Qt4 widget
  4. # Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License as
  8. # published by the Free Software Foundation; either version 2 of
  9. # the License, or any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the GPL.txt file
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. from math import floor
  20. from PyQt4.QtCore import Qt, QPointF, QRectF, QTimer, QSize, SLOT
  21. from PyQt4.QtGui import QColor, QConicalGradient, QDial, QFont, QFontMetrics
  22. from PyQt4.QtGui import QLinearGradient, QPainter, QPainterPath, QPen, QPixmap
  23. # ------------------------------------------------------------------------------------------------------------
  24. # Widget Class
  25. class PixmapDial(QDial):
  26. # enum CustomPaint
  27. CUSTOM_PAINT_NULL = 0
  28. CUSTOM_PAINT_CARLA_WET = 1
  29. CUSTOM_PAINT_CARLA_VOL = 2
  30. CUSTOM_PAINT_CARLA_L = 3
  31. CUSTOM_PAINT_CARLA_R = 4
  32. # enum Orientation
  33. HORIZONTAL = 0
  34. VERTICAL = 1
  35. HOVER_MIN = 0
  36. HOVER_MAX = 9
  37. def __init__(self, parent):
  38. QDial.__init__(self, parent)
  39. self.fPixmap = QPixmap(":/bitmaps/dial_01d.png")
  40. self.fPixmapNum = "01"
  41. self.fCustomPaint = self.CUSTOM_PAINT_NULL
  42. self.fHovered = False
  43. self.fHoverStep = self.HOVER_MIN
  44. if self.fPixmap.width() > self.fPixmap.height():
  45. self.fOrientation = self.HORIZONTAL
  46. else:
  47. self.fOrientation = self.VERTICAL
  48. self.fLabel = ""
  49. self.fLabelPos = QPointF(0.0, 0.0)
  50. self.fLabelFont = QFont()
  51. self.fLabelFont.setPointSize(6)
  52. self.fLabelWidth = 0
  53. self.fLabelHeight = 0
  54. self.fLabelGradient = QLinearGradient(0, 0, 0, 1)
  55. if self.palette().window().color().lightness() > 100:
  56. # Light background
  57. c = self.palette().dark().color()
  58. self.fColor1 = c
  59. self.fColor2 = QColor(c.red(), c.green(), c.blue(), 0)
  60. self.fColorT = [self.palette().buttonText().color(), self.palette().mid().color()]
  61. else:
  62. # Dark background
  63. self.fColor1 = QColor(0, 0, 0, 255)
  64. self.fColor2 = QColor(0, 0, 0, 0)
  65. self.fColorT = [Qt.white, Qt.darkGray]
  66. self.updateSizes()
  67. def getSize(self):
  68. return self.fSize
  69. def setCustomPaint(self, paint):
  70. self.fCustomPaint = paint
  71. self.fLabelPos.setY(self.fSize + self.fLabelHeight/2)
  72. self.update()
  73. def setEnabled(self, enabled):
  74. if self.isEnabled() != enabled:
  75. self.fPixmap.load(":/bitmaps/dial_%s%s.png" % (self.fPixmapNum, "" if enabled else "d"))
  76. self.updateSizes()
  77. self.update()
  78. QDial.setEnabled(self, enabled)
  79. def setLabel(self, label):
  80. self.fLabel = label
  81. self.fLabelWidth = QFontMetrics(self.fLabelFont).width(label)
  82. self.fLabelHeight = QFontMetrics(self.fLabelFont).height()
  83. self.fLabelPos.setX(float(self.fSize)/2.0 - float(self.fLabelWidth)/2.0)
  84. self.fLabelPos.setY(self.fSize + self.fLabelHeight)
  85. self.fLabelGradient.setColorAt(0.0, self.fColor1)
  86. self.fLabelGradient.setColorAt(0.6, self.fColor1)
  87. self.fLabelGradient.setColorAt(1.0, self.fColor2)
  88. self.fLabelGradient.setStart(0, float(self.fSize)/2.0)
  89. self.fLabelGradient.setFinalStop(0, self.fSize + self.fLabelHeight + 5)
  90. self.fLabelGradientRect = QRectF(float(self.fSize)/8.0, float(self.fSize)/2.0, float(self.fSize*6)/8.0, self.fSize+self.fLabelHeight+5)
  91. self.update()
  92. def setPixmap(self, pixmapId):
  93. self.fPixmapNum = "%02i" % pixmapId
  94. self.fPixmap.load(":/bitmaps/dial_%s%s.png" % (self.fPixmapNum, "" if self.isEnabled() else "d"))
  95. if self.fPixmap.width() > self.fPixmap.height():
  96. self.fOrientation = self.HORIZONTAL
  97. else:
  98. self.fOrientation = self.VERTICAL
  99. self.updateSizes()
  100. self.update()
  101. def minimumSizeHint(self):
  102. return QSize(self.fSize, self.fSize)
  103. def sizeHint(self):
  104. return QSize(self.fSize, self.fSize)
  105. def updateSizes(self):
  106. self.fWidth = self.fPixmap.width()
  107. self.fHeight = self.fPixmap.height()
  108. if self.fWidth < 1:
  109. self.fWidth = 1
  110. if self.fHeight < 1:
  111. self.fHeight = 1
  112. if self.fOrientation == self.HORIZONTAL:
  113. self.fSize = self.fHeight
  114. self.fCount = self.fWidth / self.fHeight
  115. else:
  116. self.fSize = self.fWidth
  117. self.fCount = self.fHeight / self.fWidth
  118. self.setMinimumSize(self.fSize, self.fSize + self.fLabelHeight + 5)
  119. self.setMaximumSize(self.fSize, self.fSize + self.fLabelHeight + 5)
  120. def enterEvent(self, event):
  121. self.fHovered = True
  122. if self.fHoverStep == self.HOVER_MIN:
  123. self.fHoverStep = self.HOVER_MIN + 1
  124. QDial.enterEvent(self, event)
  125. def leaveEvent(self, event):
  126. self.fHovered = False
  127. if self.fHoverStep == self.HOVER_MAX:
  128. self.fHoverStep = self.HOVER_MAX - 1
  129. QDial.leaveEvent(self, event)
  130. def paintEvent(self, event):
  131. event.accept()
  132. painter = QPainter(self)
  133. painter.save()
  134. painter.setRenderHint(QPainter.Antialiasing, True)
  135. if self.fLabel:
  136. if self.fCustomPaint == self.CUSTOM_PAINT_NULL:
  137. painter.setPen(self.fColor2)
  138. painter.setBrush(self.fLabelGradient)
  139. painter.drawRect(self.fLabelGradientRect)
  140. painter.setFont(self.fLabelFont)
  141. painter.setPen(self.fColorT[0 if self.isEnabled() else 1])
  142. painter.drawText(self.fLabelPos, self.fLabel)
  143. if self.isEnabled():
  144. current = float(self.value() - self.minimum())
  145. divider = float(self.maximum() - self.minimum())
  146. if divider == 0.0:
  147. return
  148. value = current / divider
  149. target = QRectF(0.0, 0.0, self.fSize, self.fSize)
  150. per = int((self.fCount - 1) * value)
  151. if self.fOrientation == self.HORIZONTAL:
  152. xpos = self.fSize * per
  153. ypos = 0.0
  154. else:
  155. xpos = 0.0
  156. ypos = self.fSize * per
  157. source = QRectF(xpos, ypos, self.fSize, self.fSize)
  158. painter.drawPixmap(target, self.fPixmap, source)
  159. # Custom knobs (Dry/Wet and Volume)
  160. if self.fCustomPaint in (self.CUSTOM_PAINT_CARLA_WET, self.CUSTOM_PAINT_CARLA_VOL):
  161. # knob color
  162. colorGreen = QColor(0x5D, 0xE7, 0x3D, 191 + self.fHoverStep*7)
  163. colorBlue = QColor(0x3E, 0xB8, 0xBE, 191 + self.fHoverStep*7)
  164. # draw small circle
  165. ballRect = QRectF(8.0, 8.0, 15.0, 15.0)
  166. ballPath = QPainterPath()
  167. ballPath.addEllipse(ballRect)
  168. #painter.drawRect(ballRect)
  169. tmpValue = (0.375 + 0.75*value)
  170. ballValue = tmpValue - floor(tmpValue)
  171. ballPoint = ballPath.pointAtPercent(ballValue)
  172. # draw arc
  173. startAngle = 216*16
  174. spanAngle = -252*16*value
  175. if self.fCustomPaint == self.CUSTOM_PAINT_CARLA_WET:
  176. painter.setBrush(colorBlue)
  177. painter.setPen(QPen(colorBlue, 0))
  178. painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2))
  179. gradient = QConicalGradient(15.5, 15.5, -45)
  180. gradient.setColorAt(0.0, colorBlue)
  181. gradient.setColorAt(0.125, colorBlue)
  182. gradient.setColorAt(0.625, colorGreen)
  183. gradient.setColorAt(0.75, colorGreen)
  184. gradient.setColorAt(0.76, colorGreen)
  185. gradient.setColorAt(1.0, colorGreen)
  186. painter.setBrush(gradient)
  187. painter.setPen(QPen(gradient, 3))
  188. else:
  189. painter.setBrush(colorBlue)
  190. painter.setPen(QPen(colorBlue, 0))
  191. painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2))
  192. painter.setBrush(colorBlue)
  193. painter.setPen(QPen(colorBlue, 3))
  194. painter.drawArc(4.0, 4.0, 26.0, 26.0, startAngle, spanAngle)
  195. # Custom knobs (L and R)
  196. elif self.fCustomPaint in (self.CUSTOM_PAINT_CARLA_L, self.CUSTOM_PAINT_CARLA_R):
  197. # knob color
  198. color = QColor(0xAD + self.fHoverStep*5, 0xD5 + self.fHoverStep*4, 0x4B + self.fHoverStep*5)
  199. # draw small circle
  200. ballRect = QRectF(7.0, 8.0, 11.0, 12.0)
  201. ballPath = QPainterPath()
  202. ballPath.addEllipse(ballRect)
  203. #painter.drawRect(ballRect)
  204. tmpValue = (0.375 + 0.75*value)
  205. ballValue = tmpValue - floor(tmpValue)
  206. ballPoint = ballPath.pointAtPercent(ballValue)
  207. painter.setBrush(color)
  208. painter.setPen(QPen(color, 0))
  209. painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.0, 2.0))
  210. # draw arc
  211. if self.fCustomPaint == self.CUSTOM_PAINT_CARLA_L:
  212. startAngle = 216*16
  213. spanAngle = -252.0*16*value
  214. elif self.fCustomPaint == self.CUSTOM_PAINT_CARLA_R:
  215. startAngle = 324.0*16
  216. spanAngle = 252.0*16*(1.0-value)
  217. else:
  218. return
  219. painter.setPen(QPen(color, 2))
  220. painter.drawArc(3.5, 4.5, 22.0, 22.0, startAngle, spanAngle)
  221. if self.HOVER_MIN < self.fHoverStep < self.HOVER_MAX:
  222. self.fHoverStep += 1 if self.fHovered else -1
  223. QTimer.singleShot(20, self, SLOT("update()"))
  224. else: # isEnabled()
  225. target = QRectF(0.0, 0.0, self.fSize, self.fSize)
  226. painter.drawPixmap(target, self.fPixmap, target)
  227. painter.restore()
  228. def resizeEvent(self, event):
  229. self.updateSizes()
  230. QDial.resizeEvent(self, event)