Cleanup
[carla.git] / source / frontend / widgets / commondial.py
bloba615cdeae898dcd08ef0d8bedfed9c9f2f8b7a14
1 #!/usr/bin/env python3
2 # SPDX-FileCopyrightText: 2011-2024 Filipe Coelho <falktx@falktx.com>
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # ---------------------------------------------------------------------------------------------------------------------
6 # Imports (Global)
8 from math import isnan
10 from qt_compat import qt_config
12 if qt_config == 5:
13 from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QPointF, QRectF
14 from PyQt5.QtGui import QColor, QFont, QLinearGradient, QPainter
15 from PyQt5.QtWidgets import QDial
16 elif qt_config == 6:
17 from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QPointF, QRectF
18 from PyQt6.QtGui import QColor, QFont, QLinearGradient, QPainter
19 from PyQt6.QtWidgets import QDial
21 # ---------------------------------------------------------------------------------------------------------------------
22 # Widget Class
24 # to be implemented by subclasses
25 #def updateSizes(self):
26 #def paintDial(self, painter):
28 class CommonDial(QDial):
29 # enum CustomPaintMode
30 CUSTOM_PAINT_MODE_NULL = 0 # default (NOTE: only this mode has label gradient)
31 CUSTOM_PAINT_MODE_CARLA_WET = 1 # color blue-green gradient (reserved #3)
32 CUSTOM_PAINT_MODE_CARLA_VOL = 2 # color blue (reserved #3)
33 CUSTOM_PAINT_MODE_CARLA_L = 3 # color yellow (reserved #4)
34 CUSTOM_PAINT_MODE_CARLA_R = 4 # color yellow (reserved #4)
35 CUSTOM_PAINT_MODE_CARLA_PAN = 5 # color yellow (reserved #3)
36 CUSTOM_PAINT_MODE_COLOR = 6 # color, selectable (reserved #3)
37 CUSTOM_PAINT_MODE_ZITA = 7 # custom zita knob (reserved #6)
38 CUSTOM_PAINT_MODE_NO_GRADIENT = 8 # skip label gradient
40 # enum Orientation
41 HORIZONTAL = 0
42 VERTICAL = 1
44 HOVER_MIN = 0
45 HOVER_MAX = 9
47 MODE_DEFAULT = 0
48 MODE_LINEAR = 1
50 # signals
51 dragStateChanged = pyqtSignal(bool)
52 realValueChanged = pyqtSignal(float)
54 def __init__(self, parent, index):
55 QDial.__init__(self, parent)
57 self.fDialMode = self.MODE_LINEAR
59 self.fMinimum = 0.0
60 self.fMaximum = 1.0
61 self.fRealValue = 0.0
62 self.fPrecision = 10000
63 self.fIsInteger = False
65 self.fIsHovered = False
66 self.fIsPressed = False
67 self.fHoverStep = self.HOVER_MIN
69 self.fLastDragPos = None
70 self.fLastDragValue = 0.0
72 self.fIndex = index
74 self.fLabel = ""
75 self.fLabelPos = QPointF(0.0, 0.0)
76 self.fLabelFont = QFont(self.font())
77 self.fLabelFont.setPixelSize(8)
78 self.fLabelWidth = 0
79 self.fLabelHeight = 0
81 if self.palette().window().color().lightness() > 100:
82 # Light background
83 c = self.palette().dark().color()
84 self.fLabelGradientColor1 = c
85 self.fLabelGradientColor2 = QColor(c.red(), c.green(), c.blue(), 0)
86 self.fLabelGradientColorT = [self.palette().buttonText().color(), self.palette().mid().color()]
87 else:
88 # Dark background
89 self.fLabelGradientColor1 = QColor(0, 0, 0, 255)
90 self.fLabelGradientColor2 = QColor(0, 0, 0, 0)
91 self.fLabelGradientColorT = [Qt.white, Qt.darkGray]
93 self.fLabelGradient = QLinearGradient(0, 0, 0, 1)
94 self.fLabelGradient.setColorAt(0.0, self.fLabelGradientColor1)
95 self.fLabelGradient.setColorAt(0.6, self.fLabelGradientColor1)
96 self.fLabelGradient.setColorAt(1.0, self.fLabelGradientColor2)
98 self.fLabelGradientRect = QRectF(0.0, 0.0, 0.0, 0.0)
100 self.fCustomPaintMode = self.CUSTOM_PAINT_MODE_NULL
101 self.fCustomPaintColor = QColor(0xff, 0xff, 0xff)
103 # Fake internal value, custom precision
104 QDial.setMinimum(self, 0)
105 QDial.setMaximum(self, self.fPrecision)
106 QDial.setValue(self, 0)
108 self.valueChanged.connect(self.slot_valueChanged)
110 def forceWhiteLabelGradientText(self):
111 self.fLabelGradientColor1 = QColor(0, 0, 0, 255)
112 self.fLabelGradientColor2 = QColor(0, 0, 0, 0)
113 self.fLabelGradientColorT = [Qt.white, Qt.darkGray]
115 def setLabelColor(self, enabled, disabled):
116 self.fLabelGradientColor1 = QColor(0, 0, 0, 255)
117 self.fLabelGradientColor2 = QColor(0, 0, 0, 0)
118 self.fLabelGradientColorT = [enabled, disabled]
120 def getIndex(self):
121 return self.fIndex
123 def setIndex(self, index):
124 self.fIndex = index
126 def setPrecision(self, value, isInteger):
127 self.fPrecision = value
128 self.fIsInteger = isInteger
129 QDial.setMaximum(self, int(value))
131 def setMinimum(self, value):
132 self.fMinimum = value
134 def setMaximum(self, value):
135 self.fMaximum = value
137 def rvalue(self):
138 return self.fRealValue
140 def setValue(self, value, emitSignal=False):
141 if self.fRealValue == value or isnan(value):
142 return
144 if value <= self.fMinimum:
145 qtValue = 0
146 self.fRealValue = self.fMinimum
148 elif value >= self.fMaximum:
149 qtValue = int(self.fPrecision)
150 self.fRealValue = self.fMaximum
152 else:
153 qtValue = round(float(value - self.fMinimum) / float(self.fMaximum - self.fMinimum) * self.fPrecision)
154 self.fRealValue = value
156 # Block change signal, we'll handle it ourselves
157 self.blockSignals(True)
158 QDial.setValue(self, qtValue)
159 self.blockSignals(False)
161 if emitSignal:
162 self.realValueChanged.emit(self.fRealValue)
164 def setCustomPaintMode(self, paintMode):
165 if self.fCustomPaintMode == paintMode:
166 return
168 self.fCustomPaintMode = paintMode
169 self.update()
171 def setCustomPaintColor(self, color):
172 if self.fCustomPaintColor == color:
173 return
175 self.fCustomPaintColor = color
176 self.update()
178 def setLabel(self, label):
179 if self.fLabel == label:
180 return
182 self.fLabel = label
183 self.updateSizes()
184 self.update()
186 @pyqtSlot(int)
187 def slot_valueChanged(self, value):
188 self.fRealValue = float(value)/self.fPrecision * (self.fMaximum - self.fMinimum) + self.fMinimum
189 self.realValueChanged.emit(self.fRealValue)
191 def enterEvent(self, event):
192 self.fIsHovered = True
193 if self.fHoverStep == self.HOVER_MIN:
194 self.fHoverStep = self.HOVER_MIN + 1
195 QDial.enterEvent(self, event)
197 def leaveEvent(self, event):
198 self.fIsHovered = False
199 if self.fHoverStep == self.HOVER_MAX:
200 self.fHoverStep = self.HOVER_MAX - 1
201 QDial.leaveEvent(self, event)
203 def mousePressEvent(self, event):
204 if self.fDialMode == self.MODE_DEFAULT:
205 QDial.mousePressEvent(self, event)
206 return
208 if event.button() == Qt.LeftButton:
209 self.fIsPressed = True
210 self.fLastDragPos = event.pos()
211 self.fLastDragValue = self.fRealValue
212 self.dragStateChanged.emit(True)
214 def mouseMoveEvent(self, event):
215 if self.fDialMode == self.MODE_DEFAULT:
216 QDial.mouseMoveEvent(self, event)
217 return
219 if not self.fIsPressed:
220 return
222 diff = (self.fMaximum - self.fMinimum) / 4.0
223 pos = event.pos()
224 dx = diff * float(pos.x() - self.fLastDragPos.x()) / self.width()
225 dy = diff * float(pos.y() - self.fLastDragPos.y()) / self.height()
226 value = self.fLastDragValue + dx - dy
228 if value < self.fMinimum:
229 value = self.fMinimum
230 elif value > self.fMaximum:
231 value = self.fMaximum
232 elif self.fIsInteger:
233 value = float(round(value))
235 self.setValue(value, True)
237 def mouseReleaseEvent(self, event):
238 if self.fDialMode == self.MODE_DEFAULT:
239 QDial.mouseReleaseEvent(self, event)
240 return
242 if self.fIsPressed:
243 self.fIsPressed = False
244 self.dragStateChanged.emit(False)
246 def paintEvent(self, event):
247 painter = QPainter(self)
248 event.accept()
250 painter.save()
251 painter.setRenderHint(QPainter.Antialiasing, True)
253 if self.fLabel:
254 if self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_NULL:
255 painter.setPen(self.fLabelGradientColor2)
256 painter.setBrush(self.fLabelGradient)
257 painter.drawRect(self.fLabelGradientRect)
259 painter.setFont(self.fLabelFont)
260 painter.setPen(self.fLabelGradientColorT[0 if self.isEnabled() else 1])
261 painter.drawText(self.fLabelPos, self.fLabel)
263 self.paintDial(painter)
265 painter.restore()
267 def resizeEvent(self, event):
268 QDial.resizeEvent(self, event)
269 self.updateSizes()
271 # ---------------------------------------------------------------------------------------------------------------------