2 # SPDX-FileCopyrightText: 2011-2024 Filipe Coelho <falktx@falktx.com>
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # ---------------------------------------------------------------------------------------------------------------------
8 from math
import cos
, floor
, pi
, sin
10 from qt_compat
import qt_config
13 from PyQt5
.QtCore
import pyqtSlot
, Qt
, QEvent
, QPointF
, QRectF
, QTimer
, QSize
14 from PyQt5
.QtGui
import QColor
, QConicalGradient
, QFontMetrics
, QPainterPath
, QPen
, QPixmap
15 from PyQt5
.QtWidgets
import QDial
17 from PyQt6
.QtCore
import pyqtSlot
, Qt
, QEvent
, QPointF
, QRectF
, QTimer
, QSize
18 from PyQt6
.QtGui
import QColor
, QConicalGradient
, QFontMetrics
, QPainterPath
, QPen
, QPixmap
19 from PyQt6
.QtWidgets
import QDial
21 from .commondial
import CommonDial
22 from carla_shared
import fontMetricsHorizontalAdvance
24 # ---------------------------------------------------------------------------------------------------------------------
27 class PixmapDial(CommonDial
):
28 def __init__(self
, parent
, index
=0):
29 CommonDial
.__init
__(self
, parent
, index
)
31 self
.fPixmap
= QPixmap(":/bitmaps/dial_01d.png")
32 self
.fPixmapNum
= "01"
34 if self
.fPixmap
.width() > self
.fPixmap
.height():
35 self
.fPixmapOrientation
= self
.HORIZONTAL
37 self
.fPixmapOrientation
= self
.VERTICAL
41 def getBaseSize(self
):
42 return self
.fPixmapBaseSize
44 def updateSizes(self
):
45 self
.fPixmapWidth
= self
.fPixmap
.width()
46 self
.fPixmapHeight
= self
.fPixmap
.height()
48 if self
.fPixmapWidth
< 1:
51 if self
.fPixmapHeight
< 1:
52 self
.fPixmapHeight
= 1
54 if self
.fPixmapOrientation
== self
.HORIZONTAL
:
55 self
.fPixmapBaseSize
= self
.fPixmapHeight
56 self
.fPixmapLayersCount
= self
.fPixmapWidth
/ self
.fPixmapHeight
58 self
.fPixmapBaseSize
= self
.fPixmapWidth
59 self
.fPixmapLayersCount
= self
.fPixmapHeight
/ self
.fPixmapWidth
61 self
.setMinimumSize(self
.fPixmapBaseSize
, self
.fPixmapBaseSize
+ self
.fLabelHeight
+ 5)
62 self
.setMaximumSize(self
.fPixmapBaseSize
, self
.fPixmapBaseSize
+ self
.fLabelHeight
+ 5)
69 metrics
= QFontMetrics(self
.fLabelFont
)
70 self
.fLabelWidth
= fontMetricsHorizontalAdvance(metrics
, self
.fLabel
)
71 self
.fLabelHeight
= metrics
.height()
73 self
.fLabelPos
.setX(float(self
.fPixmapBaseSize
)/2.0 - float(self
.fLabelWidth
)/2.0)
75 if self
.fPixmapNum
in ("01", "02", "07", "08", "09", "10"):
76 self
.fLabelPos
.setY(self
.fPixmapBaseSize
+ self
.fLabelHeight
)
77 elif self
.fPixmapNum
in ("11",):
78 self
.fLabelPos
.setY(self
.fPixmapBaseSize
+ self
.fLabelHeight
*2/3)
80 self
.fLabelPos
.setY(self
.fPixmapBaseSize
+ self
.fLabelHeight
/2)
82 self
.fLabelGradient
.setStart(0, float(self
.fPixmapBaseSize
)/2.0)
83 self
.fLabelGradient
.setFinalStop(0, self
.fPixmapBaseSize
+ self
.fLabelHeight
+ 5)
85 self
.fLabelGradientRect
= QRectF(float(self
.fPixmapBaseSize
)/8.0, float(self
.fPixmapBaseSize
)/2.0, float(self
.fPixmapBaseSize
*3)/4.0, self
.fPixmapBaseSize
+self
.fLabelHeight
+5)
87 def setPixmap(self
, pixmapId
):
88 self
.fPixmapNum
= "%02i" % pixmapId
89 self
.fPixmap
.load(":/bitmaps/dial_%s%s.png" % (self
.fPixmapNum
, "" if self
.isEnabled() else "d"))
91 if self
.fPixmap
.width() > self
.fPixmap
.height():
92 self
.fPixmapOrientation
= self
.HORIZONTAL
94 self
.fPixmapOrientation
= self
.VERTICAL
97 if self
.fCustomPaintMode
== self
.CUSTOM_PAINT_MODE_NULL
:
98 # reserved for carla-wet, carla-vol, carla-pan and color
99 if self
.fPixmapNum
== "03":
100 self
.fCustomPaintMode
= self
.CUSTOM_PAINT_MODE_COLOR
102 # reserved for carla-L and carla-R
103 elif self
.fPixmapNum
== "04":
104 self
.fCustomPaintMode
= self
.CUSTOM_PAINT_MODE_CARLA_L
107 elif self
.fPixmapNum
== "06":
108 self
.fCustomPaintMode
= self
.CUSTOM_PAINT_MODE_ZITA
114 def slot_updatePixmap(self
):
115 self
.setPixmap(int(self
.fPixmapNum
))
117 def minimumSizeHint(self
):
118 return QSize(self
.fPixmapBaseSize
, self
.fPixmapBaseSize
)
121 return QSize(self
.fPixmapBaseSize
, self
.fPixmapBaseSize
)
123 def changeEvent(self
, event
):
124 CommonDial
.changeEvent(self
, event
)
126 # Force pixmap update if enabled state changes
127 if event
.type() == QEvent
.EnabledChange
:
128 self
.setPixmap(int(self
.fPixmapNum
))
130 def paintDial(self
, painter
):
132 normValue
= float(self
.fRealValue
- self
.fMinimum
) / float(self
.fMaximum
- self
.fMinimum
)
133 target
= QRectF(0.0, 0.0, self
.fPixmapBaseSize
, self
.fPixmapBaseSize
)
135 curLayer
= int((self
.fPixmapLayersCount
- 1) * normValue
)
137 if self
.fPixmapOrientation
== self
.HORIZONTAL
:
138 xpos
= self
.fPixmapBaseSize
* curLayer
142 ypos
= self
.fPixmapBaseSize
* curLayer
144 source
= QRectF(xpos
, ypos
, self
.fPixmapBaseSize
, self
.fPixmapBaseSize
)
145 painter
.drawPixmap(target
, self
.fPixmap
, source
)
147 # Custom knobs (Dry/Wet and Volume)
148 if self
.fCustomPaintMode
in (self
.CUSTOM_PAINT_MODE_CARLA_WET
, self
.CUSTOM_PAINT_MODE_CARLA_VOL
):
150 colorGreen
= QColor(0x5D, 0xE7, 0x3D).lighter(100 + self
.fHoverStep
*6)
151 colorBlue
= QColor(0x3E, 0xB8, 0xBE).lighter(100 + self
.fHoverStep
*6)
154 ballRect
= QRectF(8.0, 8.0, 15.0, 15.0)
155 ballPath
= QPainterPath()
156 ballPath
.addEllipse(ballRect
)
157 #painter.drawRect(ballRect)
158 tmpValue
= (0.375 + 0.75*normValue
)
159 ballValue
= tmpValue
- floor(tmpValue
)
160 ballPoint
= ballPath
.pointAtPercent(ballValue
)
164 spanAngle
= -252*16*normValue
166 if self
.fCustomPaintMode
== self
.CUSTOM_PAINT_MODE_CARLA_WET
:
167 painter
.setBrush(colorBlue
)
168 painter
.setPen(QPen(colorBlue
, 0))
169 painter
.drawEllipse(QRectF(ballPoint
.x(), ballPoint
.y(), 2.2, 2.2))
171 gradient
= QConicalGradient(15.5, 15.5, -45)
172 gradient
.setColorAt(0.0, colorBlue
)
173 gradient
.setColorAt(0.125, colorBlue
)
174 gradient
.setColorAt(0.625, colorGreen
)
175 gradient
.setColorAt(0.75, colorGreen
)
176 gradient
.setColorAt(0.76, colorGreen
)
177 gradient
.setColorAt(1.0, colorGreen
)
178 painter
.setBrush(gradient
)
179 painter
.setPen(QPen(gradient
, 3))
182 painter
.setBrush(colorBlue
)
183 painter
.setPen(QPen(colorBlue
, 0))
184 painter
.drawEllipse(QRectF(ballPoint
.x(), ballPoint
.y(), 2.2, 2.2))
186 painter
.setBrush(colorBlue
)
187 painter
.setPen(QPen(colorBlue
, 3))
189 painter
.drawArc(4.0, 4.0, 26.0, 26.0, startAngle
, spanAngle
)
191 # Custom knobs (L and R)
192 elif self
.fCustomPaintMode
in (self
.CUSTOM_PAINT_MODE_CARLA_L
, self
.CUSTOM_PAINT_MODE_CARLA_R
):
194 color
= QColor(0xAD, 0xD5, 0x48).lighter(100 + self
.fHoverStep
*6)
197 ballRect
= QRectF(7.0, 8.0, 11.0, 12.0)
198 ballPath
= QPainterPath()
199 ballPath
.addEllipse(ballRect
)
200 #painter.drawRect(ballRect)
201 tmpValue
= (0.375 + 0.75*normValue
)
202 ballValue
= tmpValue
- floor(tmpValue
)
203 ballPoint
= ballPath
.pointAtPercent(ballValue
)
205 painter
.setBrush(color
)
206 painter
.setPen(QPen(color
, 0))
207 painter
.drawEllipse(QRectF(ballPoint
.x(), ballPoint
.y(), 2.0, 2.0))
210 if self
.fCustomPaintMode
== self
.CUSTOM_PAINT_MODE_CARLA_L
:
212 spanAngle
= -252.0*16*normValue
214 startAngle
= 324.0*16
215 spanAngle
= 252.0*16*(1.0-normValue
)
217 painter
.setPen(QPen(color
, 2))
218 painter
.drawArc(3.5, 4.5, 22.0, 22.0, startAngle
, spanAngle
)
220 # Custom knobs (Color)
221 elif self
.fCustomPaintMode
== self
.CUSTOM_PAINT_MODE_COLOR
:
223 color
= self
.fCustomPaintColor
.lighter(100 + self
.fHoverStep
*6)
226 ballRect
= QRectF(8.0, 8.0, 15.0, 15.0)
227 ballPath
= QPainterPath()
228 ballPath
.addEllipse(ballRect
)
229 tmpValue
= (0.375 + 0.75*normValue
)
230 ballValue
= tmpValue
- floor(tmpValue
)
231 ballPoint
= ballPath
.pointAtPercent(ballValue
)
235 spanAngle
= -252*16*normValue
237 painter
.setBrush(color
)
238 painter
.setPen(QPen(color
, 0))
239 painter
.drawEllipse(QRectF(ballPoint
.x(), ballPoint
.y(), 2.2, 2.2))
241 painter
.setBrush(color
)
242 painter
.setPen(QPen(color
, 3))
243 painter
.drawArc(4.0, 4.0, 26.0, 26.0, startAngle
, spanAngle
)
245 # Custom knobs (Zita)
246 elif self
.fCustomPaintMode
== self
.CUSTOM_PAINT_MODE_ZITA
:
247 a
= normValue
* pi
* 1.5 - 2.35
253 painter
.setBrush(Qt
.black
)
254 painter
.setPen(QPen(Qt
.black
, 2))
255 painter
.drawLine(QPointF(11.0, 11.0), QPointF(x
, y
))
262 if self
.HOVER_MIN
< self
.fHoverStep
< self
.HOVER_MAX
:
263 self
.fHoverStep
+= 1 if self
.fIsHovered
else -1
264 QTimer
.singleShot(20, self
.update
)
267 target
= QRectF(0.0, 0.0, self
.fPixmapBaseSize
, self
.fPixmapBaseSize
)
268 painter
.drawPixmap(target
, self
.fPixmap
, target
)
270 # ---------------------------------------------------------------------------------------------------------------------