Chris@58
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@32
|
2
|
Chris@32
|
3 /*
|
Chris@59
|
4 Sonic Visualiser
|
Chris@59
|
5 An audio file viewer and annotation editor.
|
Chris@59
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@32
|
7
|
Chris@59
|
8 This program is free software; you can redistribute it and/or
|
Chris@59
|
9 modify it under the terms of the GNU General Public License as
|
Chris@59
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@59
|
11 License, or (at your option) any later version. See the file
|
Chris@59
|
12 COPYING included with this distribution for more information.
|
Chris@32
|
13 */
|
Chris@32
|
14
|
Chris@32
|
15 /*
|
Chris@32
|
16 This is a modified version of a source file from the KDE
|
Chris@32
|
17 libraries. Copyright (c) 1998-2004 Jörg Habenicht, Richard J
|
Chris@32
|
18 Moore, Chris Cannam and others, distributed under the GNU Lesser
|
Chris@32
|
19 General Public License.
|
Chris@32
|
20
|
Chris@32
|
21 Ported to Qt4 by Chris Cannam.
|
Chris@32
|
22 */
|
Chris@32
|
23
|
Chris@32
|
24
|
Chris@32
|
25 #include "LEDButton.h"
|
Chris@32
|
26
|
Chris@32
|
27 #include <QPainter>
|
Chris@32
|
28 #include <QImage>
|
Chris@32
|
29 #include <QColor>
|
Chris@33
|
30 #include <QMouseEvent>
|
Chris@32
|
31
|
Chris@34
|
32 #include <iostream>
|
Chris@34
|
33
|
Chris@32
|
34
|
Chris@32
|
35 class LEDButton::LEDButtonPrivate
|
Chris@32
|
36 {
|
Chris@32
|
37 friend class LEDButton;
|
Chris@32
|
38
|
Chris@32
|
39 int dark_factor;
|
Chris@32
|
40 QColor offcolor;
|
Chris@32
|
41 QPixmap *off_map;
|
Chris@32
|
42 QPixmap *on_map;
|
Chris@32
|
43 };
|
Chris@32
|
44
|
Chris@32
|
45
|
Chris@32
|
46 LEDButton::LEDButton(QWidget *parent) :
|
Chris@32
|
47 QWidget(parent),
|
Chris@34
|
48 led_state(true)
|
Chris@32
|
49 {
|
Chris@32
|
50 QColor col(Qt::green);
|
Chris@32
|
51 d = new LEDButton::LEDButtonPrivate;
|
Chris@32
|
52 d->dark_factor = 300;
|
Chris@32
|
53 d->offcolor = col.dark(300);
|
Chris@32
|
54 d->off_map = 0;
|
Chris@32
|
55 d->on_map = 0;
|
Chris@32
|
56
|
Chris@32
|
57 setColor(col);
|
Chris@32
|
58 }
|
Chris@32
|
59
|
Chris@32
|
60
|
Chris@32
|
61 LEDButton::LEDButton(const QColor& col, QWidget *parent) :
|
Chris@32
|
62 QWidget(parent),
|
Chris@34
|
63 led_state(true)
|
Chris@32
|
64 {
|
Chris@32
|
65 d = new LEDButton::LEDButtonPrivate;
|
Chris@32
|
66 d->dark_factor = 300;
|
Chris@32
|
67 d->offcolor = col.dark(300);
|
Chris@32
|
68 d->off_map = 0;
|
Chris@32
|
69 d->on_map = 0;
|
Chris@32
|
70
|
Chris@32
|
71 setColor(col);
|
Chris@32
|
72 }
|
Chris@32
|
73
|
Chris@34
|
74 LEDButton::LEDButton(const QColor& col, bool state, QWidget *parent) :
|
Chris@32
|
75 QWidget(parent),
|
Chris@32
|
76 led_state(state)
|
Chris@32
|
77 {
|
Chris@32
|
78 d = new LEDButton::LEDButtonPrivate;
|
Chris@32
|
79 d->dark_factor = 300;
|
Chris@32
|
80 d->offcolor = col.dark(300);
|
Chris@32
|
81 d->off_map = 0;
|
Chris@32
|
82 d->on_map = 0;
|
Chris@32
|
83
|
Chris@32
|
84 setColor(col);
|
Chris@32
|
85 }
|
Chris@32
|
86
|
Chris@32
|
87 LEDButton::~LEDButton()
|
Chris@32
|
88 {
|
Chris@32
|
89 delete d->off_map;
|
Chris@32
|
90 delete d->on_map;
|
Chris@32
|
91 delete d;
|
Chris@32
|
92 }
|
Chris@32
|
93
|
Chris@32
|
94 void
|
Chris@33
|
95 LEDButton::mousePressEvent(QMouseEvent *e)
|
Chris@33
|
96 {
|
Chris@682
|
97 cerr << "LEDButton(" << this << ")::mousePressEvent" << endl;
|
Chris@34
|
98
|
Chris@33
|
99 if (e->buttons() & Qt::LeftButton) {
|
Chris@33
|
100 toggle();
|
Chris@34
|
101 bool newState = state();
|
Chris@587
|
102 SVDEBUG << "emitting new state " << newState << endl;
|
Chris@34
|
103 emit stateChanged(newState);
|
Chris@33
|
104 }
|
Chris@33
|
105 }
|
Chris@33
|
106
|
Chris@33
|
107 void
|
Chris@189
|
108 LEDButton::enterEvent(QEvent *)
|
Chris@189
|
109 {
|
Chris@189
|
110 emit mouseEntered();
|
Chris@189
|
111 }
|
Chris@189
|
112
|
Chris@189
|
113 void
|
Chris@189
|
114 LEDButton::leaveEvent(QEvent *)
|
Chris@189
|
115 {
|
Chris@189
|
116 emit mouseLeft();
|
Chris@189
|
117 }
|
Chris@189
|
118
|
Chris@189
|
119 void
|
Chris@32
|
120 LEDButton::paintEvent(QPaintEvent *)
|
Chris@32
|
121 {
|
Chris@32
|
122 QPainter paint;
|
Chris@32
|
123 QColor color;
|
Chris@32
|
124 QBrush brush;
|
Chris@32
|
125 QPen pen;
|
Chris@32
|
126
|
Chris@32
|
127 // First of all we want to know what area should be updated
|
Chris@32
|
128 // Initialize coordinates, width, and height of the LED
|
Chris@32
|
129 int width = this->width();
|
Chris@32
|
130
|
Chris@32
|
131 // Make sure the LED is round!
|
Chris@32
|
132 if (width > this->height())
|
Chris@32
|
133 width = this->height();
|
Chris@32
|
134 width -= 2; // leave one pixel border
|
Chris@32
|
135 if (width < 0)
|
Chris@32
|
136 width = 0;
|
Chris@32
|
137
|
Chris@34
|
138 QPixmap *tmpMap = 0;
|
Chris@34
|
139
|
Chris@34
|
140 if (led_state) {
|
Chris@34
|
141 if (d->on_map) {
|
Chris@496
|
142 if (d->on_map->size() == size()) {
|
Chris@496
|
143 paint.begin(this);
|
Chris@496
|
144 paint.drawPixmap(0, 0, *d->on_map);
|
Chris@496
|
145 paint.end();
|
Chris@496
|
146 return;
|
Chris@496
|
147 } else {
|
Chris@496
|
148 delete d->on_map;
|
Chris@496
|
149 d->on_map = 0;
|
Chris@496
|
150 }
|
Chris@34
|
151 }
|
Chris@34
|
152 } else {
|
Chris@34
|
153 if (d->off_map) {
|
Chris@496
|
154 if (d->off_map->size() == size()) {
|
Chris@496
|
155 paint.begin(this);
|
Chris@496
|
156 paint.drawPixmap(0, 0, *d->off_map);
|
Chris@496
|
157 paint.end();
|
Chris@496
|
158 return;
|
Chris@496
|
159 } else {
|
Chris@496
|
160 delete d->off_map;
|
Chris@496
|
161 d->off_map = 0;
|
Chris@496
|
162 }
|
Chris@34
|
163 }
|
Chris@34
|
164 }
|
Chris@32
|
165
|
Chris@32
|
166 int scale = 1;
|
Chris@34
|
167 width *= scale;
|
Chris@32
|
168
|
Chris@34
|
169 tmpMap = new QPixmap(width, width);
|
Chris@34
|
170 tmpMap->fill(palette().background().color());
|
Chris@34
|
171 paint.begin(tmpMap);
|
Chris@32
|
172
|
Chris@33
|
173 paint.setRenderHint(QPainter::Antialiasing, true);
|
Chris@32
|
174
|
Chris@32
|
175 // Set the color of the LED according to given parameters
|
Chris@32
|
176 color = (led_state) ? led_color : d->offcolor;
|
Chris@32
|
177
|
Chris@32
|
178 // Set the brush to SolidPattern, this fills the entire area
|
Chris@32
|
179 // of the ellipse which is drawn first
|
Chris@32
|
180 brush.setStyle(Qt::SolidPattern);
|
Chris@32
|
181 brush.setColor(color);
|
Chris@32
|
182 paint.setBrush(brush);
|
Chris@32
|
183
|
Chris@32
|
184 // Draws a "flat" LED with the given color:
|
Chris@32
|
185 paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 );
|
Chris@32
|
186
|
Chris@32
|
187 // Draw the bright light spot of the LED now, using modified "old"
|
Chris@32
|
188 // painter routine taken from KDEUI´s LEDButton widget:
|
Chris@32
|
189
|
Chris@32
|
190 // Setting the new width of the pen is essential to avoid "pixelized"
|
Chris@32
|
191 // shadow like it can be observed with the old LED code
|
Chris@32
|
192 pen.setWidth( 2 * scale );
|
Chris@32
|
193
|
Chris@32
|
194 // shrink the light on the LED to a size about 2/3 of the complete LED
|
Chris@32
|
195 int pos = width/5 + 1;
|
Chris@32
|
196 int light_width = width;
|
Chris@32
|
197 light_width *= 2;
|
Chris@32
|
198 light_width /= 3;
|
Chris@32
|
199
|
Chris@32
|
200 // Calculate the LED´s "light factor":
|
Chris@32
|
201 int light_quote = (130*2/(light_width?light_width:1))+100;
|
Chris@32
|
202
|
Chris@32
|
203 // Now draw the bright spot on the LED:
|
Chris@32
|
204 while (light_width) {
|
Chris@32
|
205 color = color.light( light_quote ); // make color lighter
|
Chris@32
|
206 pen.setColor( color ); // set color as pen color
|
Chris@32
|
207 paint.setPen( pen ); // select the pen for drawing
|
Chris@32
|
208 paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle)
|
Chris@32
|
209 light_width--;
|
Chris@32
|
210 if (!light_width)
|
Chris@32
|
211 break;
|
Chris@32
|
212 paint.drawEllipse( pos, pos, light_width, light_width );
|
Chris@32
|
213 light_width--;
|
Chris@32
|
214 if (!light_width)
|
Chris@32
|
215 break;
|
Chris@32
|
216 paint.drawEllipse( pos, pos, light_width, light_width );
|
Chris@32
|
217 pos++; light_width--;
|
Chris@32
|
218 }
|
Chris@32
|
219
|
Chris@32
|
220 // Drawing of bright spot finished, now draw a thin border
|
Chris@32
|
221 // around the LED which resembles a shadow with light coming
|
Chris@32
|
222 // from the upper left.
|
Chris@32
|
223
|
Chris@33
|
224 // pen.setWidth( 2 * scale + 1 ); // ### shouldn't this value be smaller for smaller LEDs?
|
Chris@33
|
225 pen.setWidth(2 * scale);
|
Chris@32
|
226 brush.setStyle(Qt::NoBrush);
|
Chris@32
|
227 paint.setBrush(brush); // This avoids filling of the ellipse
|
Chris@32
|
228
|
Chris@32
|
229 // Set the initial color value to colorGroup().light() (bright) and start
|
Chris@32
|
230 // drawing the shadow border at 45° (45*16 = 720).
|
Chris@32
|
231
|
Chris@32
|
232 int angle = -720;
|
Chris@32
|
233 color = palette().light().color();
|
Chris@32
|
234
|
Chris@32
|
235 for (int arc = 120; arc < 2880; arc += 240) {
|
Chris@32
|
236 pen.setColor(color);
|
Chris@32
|
237 paint.setPen(pen);
|
Chris@32
|
238 int w = width - pen.width()/2 - scale + 1;
|
Chris@33
|
239 paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle + arc, 240);
|
Chris@33
|
240 paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle - arc, 240);
|
Chris@32
|
241 color = color.dark(110); //FIXME: this should somehow use the contrast value
|
Chris@32
|
242 } // end for ( angle = 720; angle < 6480; angle += 160 )
|
Chris@32
|
243
|
Chris@32
|
244 paint.end();
|
Chris@32
|
245 //
|
Chris@32
|
246 // painting done
|
Chris@32
|
247
|
Chris@34
|
248 QPixmap *&dest = led_state ? d->on_map : d->off_map;
|
Chris@34
|
249
|
Chris@34
|
250 if (scale > 1) {
|
Chris@34
|
251
|
Chris@32
|
252 QImage i = tmpMap->toImage();
|
Chris@33
|
253 width /= scale;
|
Chris@32
|
254 delete tmpMap;
|
Chris@33
|
255 dest = new QPixmap(QPixmap::fromImage
|
Chris@33
|
256 (i.scaled(width, width,
|
Chris@33
|
257 Qt::KeepAspectRatio,
|
Chris@33
|
258 Qt::SmoothTransformation)));
|
Chris@34
|
259
|
Chris@34
|
260 } else {
|
Chris@34
|
261
|
Chris@34
|
262 dest = tmpMap;
|
Chris@32
|
263 }
|
Chris@34
|
264
|
Chris@34
|
265 paint.begin(this);
|
Chris@34
|
266 paint.drawPixmap(0, 0, *dest);
|
Chris@34
|
267 paint.end();
|
Chris@32
|
268 }
|
Chris@32
|
269
|
Chris@34
|
270 bool
|
Chris@32
|
271 LEDButton::state() const
|
Chris@32
|
272 {
|
Chris@32
|
273 return led_state;
|
Chris@32
|
274 }
|
Chris@32
|
275
|
Chris@32
|
276 QColor
|
Chris@32
|
277 LEDButton::color() const
|
Chris@32
|
278 {
|
Chris@32
|
279 return led_color;
|
Chris@32
|
280 }
|
Chris@32
|
281
|
Chris@32
|
282 void
|
Chris@34
|
283 LEDButton::setState( bool state )
|
Chris@32
|
284 {
|
Chris@32
|
285 if (led_state != state)
|
Chris@32
|
286 {
|
Chris@32
|
287 led_state = state;
|
Chris@32
|
288 update();
|
Chris@32
|
289 }
|
Chris@32
|
290 }
|
Chris@32
|
291
|
Chris@32
|
292 void
|
Chris@32
|
293 LEDButton::toggleState()
|
Chris@32
|
294 {
|
Chris@34
|
295 led_state = (led_state == true) ? false : true;
|
Chris@32
|
296 // setColor(led_color);
|
Chris@32
|
297 update();
|
Chris@32
|
298 }
|
Chris@32
|
299
|
Chris@32
|
300 void
|
Chris@32
|
301 LEDButton::setColor(const QColor& col)
|
Chris@32
|
302 {
|
Chris@32
|
303 if(led_color!=col) {
|
Chris@32
|
304 led_color = col;
|
Chris@32
|
305 d->offcolor = col.dark(d->dark_factor);
|
Chris@32
|
306 delete d->on_map;
|
Chris@32
|
307 d->on_map = 0;
|
Chris@32
|
308 delete d->off_map;
|
Chris@32
|
309 d->off_map = 0;
|
Chris@32
|
310 update();
|
Chris@32
|
311 }
|
Chris@32
|
312 }
|
Chris@32
|
313
|
Chris@32
|
314 void
|
Chris@32
|
315 LEDButton::setDarkFactor(int darkfactor)
|
Chris@32
|
316 {
|
Chris@32
|
317 if (d->dark_factor != darkfactor) {
|
Chris@32
|
318 d->dark_factor = darkfactor;
|
Chris@32
|
319 d->offcolor = led_color.dark(darkfactor);
|
Chris@32
|
320 update();
|
Chris@32
|
321 }
|
Chris@32
|
322 }
|
Chris@32
|
323
|
Chris@32
|
324 int
|
Chris@32
|
325 LEDButton::darkFactor() const
|
Chris@32
|
326 {
|
Chris@32
|
327 return d->dark_factor;
|
Chris@32
|
328 }
|
Chris@32
|
329
|
Chris@32
|
330 void
|
Chris@32
|
331 LEDButton::toggle()
|
Chris@32
|
332 {
|
Chris@32
|
333 toggleState();
|
Chris@32
|
334 }
|
Chris@32
|
335
|
Chris@32
|
336 void
|
Chris@32
|
337 LEDButton::on()
|
Chris@32
|
338 {
|
Chris@34
|
339 setState(true);
|
Chris@32
|
340 }
|
Chris@32
|
341
|
Chris@32
|
342 void
|
Chris@32
|
343 LEDButton::off()
|
Chris@32
|
344 {
|
Chris@34
|
345 setState(false);
|
Chris@32
|
346 }
|
Chris@32
|
347
|
Chris@32
|
348 QSize
|
Chris@32
|
349 LEDButton::sizeHint() const
|
Chris@32
|
350 {
|
Chris@33
|
351 return QSize(17, 17);
|
Chris@32
|
352 }
|
Chris@32
|
353
|
Chris@32
|
354 QSize
|
Chris@32
|
355 LEDButton::minimumSizeHint() const
|
Chris@32
|
356 {
|
Chris@33
|
357 return QSize(17, 17);
|
Chris@32
|
358 }
|
Chris@32
|
359
|