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