src/eric7/EricWidgets/EricLed.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2006 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a LED widget.
8
9 It was inspired by KLed.
10 """
11
12 import enum
13
14 from PyQt6.QtCore import pyqtSignal, Qt, QSize, QPoint
15 from PyQt6.QtGui import QColor, QRadialGradient, QPalette, QPainter, QBrush
16 from PyQt6.QtWidgets import QWidget
17
18
19 class EricLedType(enum.Enum):
20 """
21 Class defining the LED types.
22 """
23 RECTANGULAR = 0
24 CIRCULAR = 1
25
26
27 class EricLed(QWidget):
28 """
29 Class implementing a LED widget.
30 """
31 def __init__(self, parent=None, color=None, shape=EricLedType.CIRCULAR,
32 rectRatio=1):
33 """
34 Constructor
35
36 @param parent reference to parent widget
37 @type QWidget
38 @param color color of the LED
39 @type QColor
40 @param shape shape of the LED
41 @type EricLedType
42 @param rectRatio ratio width to height, if shape is rectangular
43 @type float
44 """
45 super().__init__(parent)
46
47 if color is None:
48 color = QColor("green")
49
50 self.__led_on = True
51 self.__dark_factor = 300
52 self.__offcolor = color.darker(self.__dark_factor)
53 self.__led_color = color
54 self.__framedLed = True
55 self.__shape = shape
56 self.__rectRatio = rectRatio
57
58 self.setColor(color)
59
60 def paintEvent(self, evt):
61 """
62 Protected slot handling the paint event.
63
64 @param evt paint event object
65 @type QPaintEvent
66 """
67 if self.__shape == EricLedType.CIRCULAR:
68 self.__paintRound()
69 elif self.__shape == EricLedType.RECTANGULAR:
70 self.__paintRectangular()
71
72 def __getBestRoundSize(self):
73 """
74 Private method to calculate the width of the LED.
75
76 @return new width of the LED (integer)
77 """
78 width = min(self.width(), self.height())
79 width -= 2 # leave one pixel border
80 return width > -1 and width or 0
81
82 def __paintRound(self):
83 """
84 Private method to paint a round raised LED.
85 """
86 # Initialize coordinates, width and height of the LED
87 width = self.__getBestRoundSize()
88
89 # Calculate the gradient for the LED
90 wh = width / 2
91 color = self.__led_on and self.__led_color or self.__offcolor
92 gradient = QRadialGradient(wh, wh, wh, 0.8 * wh, 0.8 * wh)
93 gradient.setColorAt(0.0, color.lighter(200))
94 gradient.setColorAt(0.6, color)
95 if self.__framedLed:
96 gradient.setColorAt(0.9, color.darker())
97 gradient.setColorAt(
98 1.0, self.palette().color(QPalette.ColorRole.Dark))
99 else:
100 gradient.setColorAt(1.0, color.darker())
101
102 # now do the drawing
103 paint = QPainter(self)
104 paint.setRenderHint(QPainter.RenderHint.Antialiasing, True)
105 paint.setBrush(QBrush(gradient))
106 paint.setPen(Qt.PenStyle.NoPen)
107 paint.drawEllipse(1, 1, width, width)
108 paint.end()
109
110 def __paintRectangular(self):
111 """
112 Private method to paint a rectangular raised LED.
113 """
114 # Initialize coordinates, width and height of the LED
115 width = self.height() * self.__rectRatio
116 left = max(0, int((self.width() - width) / 2) - 1)
117 right = min(int((self.width() + width) / 2), self.width())
118 height = self.height()
119
120 # now do the drawing
121 painter = QPainter(self)
122 painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
123 color = self.__led_on and self.__led_color or self.__offcolor
124
125 painter.setPen(color.lighter(200))
126 painter.drawLine(left, 0, left, height - 1)
127 painter.drawLine(left + 1, 0, right - 1, 0)
128 if self.__framedLed:
129 painter.setPen(self.palette().color(QPalette.ColorRole.Dark))
130 else:
131 painter.setPen(color.darker())
132 painter.drawLine(left + 1, height - 1, right - 1, height - 1)
133 painter.drawLine(right - 1, 1, right - 1, height - 1)
134 painter.fillRect(left + 1, 1, right - 2, height - 2, QBrush(color))
135 painter.end()
136
137 def isOn(self):
138 """
139 Public method to return the LED state.
140
141 @return flag indicating the light state (boolean)
142 """
143 return self.__led_on
144
145 def shape(self):
146 """
147 Public method to return the LED shape.
148
149 @return LED shape
150 @rtype EricLedType
151 """
152 return self.__shape
153
154 def ratio(self):
155 """
156 Public method to return the LED rectangular ratio [= width / height].
157
158 @return LED rectangular ratio (float)
159 """
160 return self.__rectRatio
161
162 def color(self):
163 """
164 Public method to return the LED color.
165
166 @return color of the LED (QColor)
167 """
168 return self.__led_color
169
170 def setOn(self, state):
171 """
172 Public method to set the LED to on.
173
174 @param state new state of the LED (boolean)
175 """
176 if self.__led_on != state:
177 self.__led_on = state
178 self.update()
179
180 def setShape(self, shape):
181 """
182 Public method to set the LED shape.
183
184 @param shape new LED shape
185 @type EricLedType
186 """
187 if self.__shape != shape:
188 self.__shape = shape
189 self.update()
190
191 def setRatio(self, ratio):
192 """
193 Public method to set the LED rectangular ratio (width / height).
194
195 @param ratio new LED rectangular ratio (float)
196 """
197 if self.__rectRatio != ratio:
198 self.__rectRatio = ratio
199 self.update()
200
201 def setColor(self, color):
202 """
203 Public method to set the LED color.
204
205 @param color color for the LED (QColor)
206 """
207 if self.__led_color != color:
208 self.__led_color = color
209 self.__offcolor = color.darker(self.__dark_factor)
210 self.update()
211
212 def setDarkFactor(self, darkfactor):
213 """
214 Public method to set the dark factor.
215
216 @param darkfactor value to set for the dark factor (integer)
217 """
218 if self.__dark_factor != darkfactor:
219 self.__dark_factor = darkfactor
220 self.__offcolor = self.__led_color.darker(darkfactor)
221 self.update()
222
223 def darkFactor(self):
224 """
225 Public method to return the dark factor.
226
227 @return the current dark factor (integer)
228 """
229 return self.__dark_factor
230
231 def toggle(self):
232 """
233 Public slot to toggle the LED state.
234 """
235 self.setOn(not self.__led_on)
236
237 def on(self):
238 """
239 Public slot to set the LED to on.
240 """
241 self.setOn(True)
242
243 def off(self):
244 """
245 Public slot to set the LED to off.
246 """
247 self.setOn(False)
248
249 def setFramed(self, framed):
250 """
251 Public slot to set the __framedLed attribute.
252
253 @param framed flag indicating the framed state (boolean)
254 """
255 if self.__framedLed != framed:
256 self.__framedLed = framed
257 self.__off_map = None
258 self.__on_map = None
259 self.update()
260
261 def isFramed(self):
262 """
263 Public method to return the framed state.
264
265 @return flag indicating the current framed state (boolean)
266 """
267 return self.__framedLed
268
269 def sizeHint(self):
270 """
271 Public method to give a hint about our desired size.
272
273 @return size hint (QSize)
274 """
275 return QSize(18, 18)
276
277 def minimumSizeHint(self):
278 """
279 Public method to give a hint about our minimum size.
280
281 @return size hint (QSize)
282 """
283 return QSize(18, 18)
284
285
286 class EricClickableLed(EricLed):
287 """
288 Class implementing a clickable LED widget.
289
290 @signal clicked(QPoint) emitted upon a click on the LED with the
291 left button
292 @signal middleClicked(QPoint) emitted upon a click on the LED with
293 the middle button or CTRL and left button
294 """
295 clicked = pyqtSignal(QPoint)
296 middleClicked = pyqtSignal(QPoint)
297
298 def __init__(self, parent=None, color=None, shape=EricLedType.CIRCULAR,
299 rectRatio=1):
300 """
301 Constructor
302
303 @param parent reference to parent widget
304 @type QWidget
305 @param color color of the LED
306 @type QColor
307 @param shape shape of the LED
308 @type EricLedType
309 @param rectRatio ratio width to height, if shape is rectangular
310 @type float
311 """
312 super().__init__(parent, color, shape, rectRatio)
313
314 self.setCursor(Qt.CursorShape.PointingHandCursor)
315
316 def mouseReleaseEvent(self, evt):
317 """
318 Protected method handling mouse release events.
319
320 @param evt mouse event (QMouseEvent)
321 """
322 if (
323 evt.button() == Qt.MouseButton.LeftButton and
324 self.rect().contains(evt.position().toPoint())
325 ):
326 if evt.modifiers() == Qt.KeyboardModifier.ControlModifier:
327 self.middleClicked.emit(evt.globalPosition().toPoint())
328 else:
329 self.clicked.emit(evt.globalPosition().toPoint())
330 elif (
331 evt.button() == Qt.MouseButton.MiddleButton and
332 self.rect().contains(evt.position().toPoint())
333 ):
334 self.middleClicked.emit(evt.globalPosition().toPoint())
335 else:
336 super().mouseReleaseEvent(evt)

eric ide

mercurial