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