Chris@32: /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ Chris@32: Chris@32: /* Chris@32: A waveform viewer and audio annotation editor. Chris@32: Chris Cannam, Queen Mary University of London, 2005-2006 Chris@32: Chris@32: This is experimental software. Not for distribution. Chris@32: */ Chris@32: Chris@32: /* Chris@32: This is a modified version of a source file from the KDE Chris@32: libraries. Copyright (c) 1998-2004 Jörg Habenicht, Richard J Chris@32: Moore, Chris Cannam and others, distributed under the GNU Lesser Chris@32: General Public License. Chris@32: Chris@32: Ported to Qt4 by Chris Cannam. Chris@32: */ Chris@32: Chris@32: Chris@32: #include "LEDButton.h" Chris@32: Chris@32: #include Chris@32: #include Chris@32: #include Chris@32: Chris@32: Chris@32: class LEDButton::LEDButtonPrivate Chris@32: { Chris@32: friend class LEDButton; Chris@32: Chris@32: int dark_factor; Chris@32: QColor offcolor; Chris@32: QPixmap *off_map; Chris@32: QPixmap *on_map; Chris@32: }; Chris@32: Chris@32: Chris@32: LEDButton::LEDButton(QWidget *parent) : Chris@32: QWidget(parent), Chris@32: led_state(On) Chris@32: { Chris@32: QColor col(Qt::green); Chris@32: d = new LEDButton::LEDButtonPrivate; Chris@32: d->dark_factor = 300; Chris@32: d->offcolor = col.dark(300); Chris@32: d->off_map = 0; Chris@32: d->on_map = 0; Chris@32: Chris@32: setColor(col); Chris@32: } Chris@32: Chris@32: Chris@32: LEDButton::LEDButton(const QColor& col, QWidget *parent) : Chris@32: QWidget(parent), Chris@32: led_state(On) Chris@32: { Chris@32: d = new LEDButton::LEDButtonPrivate; Chris@32: d->dark_factor = 300; Chris@32: d->offcolor = col.dark(300); Chris@32: d->off_map = 0; Chris@32: d->on_map = 0; Chris@32: Chris@32: setColor(col); Chris@32: } Chris@32: Chris@32: LEDButton::LEDButton(const QColor& col, LEDButton::State state, QWidget *parent) : Chris@32: QWidget(parent), Chris@32: led_state(state) Chris@32: { Chris@32: d = new LEDButton::LEDButtonPrivate; Chris@32: d->dark_factor = 300; Chris@32: d->offcolor = col.dark(300); Chris@32: d->off_map = 0; Chris@32: d->on_map = 0; Chris@32: Chris@32: setColor(col); Chris@32: } Chris@32: Chris@32: LEDButton::~LEDButton() Chris@32: { Chris@32: delete d->off_map; Chris@32: delete d->on_map; Chris@32: delete d; Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::paintEvent(QPaintEvent *) Chris@32: { Chris@32: QPainter paint; Chris@32: QColor color; Chris@32: QBrush brush; Chris@32: QPen pen; Chris@32: Chris@32: // First of all we want to know what area should be updated Chris@32: // Initialize coordinates, width, and height of the LED Chris@32: int width = this->width(); Chris@32: Chris@32: // Make sure the LED is round! Chris@32: if (width > this->height()) Chris@32: width = this->height(); Chris@32: width -= 2; // leave one pixel border Chris@32: if (width < 0) Chris@32: width = 0; Chris@32: Chris@32: // maybe we could stop HERE, if width <=0 ? Chris@32: Chris@32: int scale = 1; Chris@32: QPixmap *tmpMap = 0; Chris@32: bool smooth = true; Chris@32: Chris@32: if (smooth) { Chris@32: if (led_state) { Chris@32: if (d->on_map) { Chris@32: paint.begin(this); Chris@32: paint.drawPixmap(0, 0, *d->on_map); Chris@32: paint.end(); Chris@32: return; Chris@32: } Chris@32: } else { Chris@32: if (d->off_map) { Chris@32: paint.begin(this); Chris@32: paint.drawPixmap(0, 0, *d->off_map); Chris@32: paint.end(); Chris@32: return; Chris@32: } Chris@32: } Chris@32: Chris@32: scale = 3; Chris@32: width *= scale; Chris@32: Chris@32: tmpMap = new QPixmap(width, width); Chris@32: tmpMap->fill(palette().background().color()); Chris@32: paint.begin(tmpMap); Chris@32: Chris@32: } else { Chris@32: paint.begin(this); Chris@32: } Chris@32: Chris@32: paint.setRenderHint(QPainter::Antialiasing, false); Chris@32: Chris@32: // Set the color of the LED according to given parameters Chris@32: color = (led_state) ? led_color : d->offcolor; Chris@32: Chris@32: // Set the brush to SolidPattern, this fills the entire area Chris@32: // of the ellipse which is drawn first Chris@32: brush.setStyle(Qt::SolidPattern); Chris@32: brush.setColor(color); Chris@32: paint.setBrush(brush); Chris@32: Chris@32: // Draws a "flat" LED with the given color: Chris@32: paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 ); Chris@32: Chris@32: // Draw the bright light spot of the LED now, using modified "old" Chris@32: // painter routine taken from KDEUI´s LEDButton widget: Chris@32: Chris@32: // Setting the new width of the pen is essential to avoid "pixelized" Chris@32: // shadow like it can be observed with the old LED code Chris@32: pen.setWidth( 2 * scale ); Chris@32: Chris@32: // shrink the light on the LED to a size about 2/3 of the complete LED Chris@32: int pos = width/5 + 1; Chris@32: int light_width = width; Chris@32: light_width *= 2; Chris@32: light_width /= 3; Chris@32: Chris@32: // Calculate the LED´s "light factor": Chris@32: int light_quote = (130*2/(light_width?light_width:1))+100; Chris@32: Chris@32: // Now draw the bright spot on the LED: Chris@32: while (light_width) { Chris@32: color = color.light( light_quote ); // make color lighter Chris@32: pen.setColor( color ); // set color as pen color Chris@32: paint.setPen( pen ); // select the pen for drawing Chris@32: paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle) Chris@32: light_width--; Chris@32: if (!light_width) Chris@32: break; Chris@32: paint.drawEllipse( pos, pos, light_width, light_width ); Chris@32: light_width--; Chris@32: if (!light_width) Chris@32: break; Chris@32: paint.drawEllipse( pos, pos, light_width, light_width ); Chris@32: pos++; light_width--; Chris@32: } Chris@32: Chris@32: // Drawing of bright spot finished, now draw a thin border Chris@32: // around the LED which resembles a shadow with light coming Chris@32: // from the upper left. Chris@32: Chris@32: pen.setWidth( 2 * scale + 1 ); // ### shouldn't this value be smaller for smaller LEDs? Chris@32: brush.setStyle(Qt::NoBrush); Chris@32: paint.setBrush(brush); // This avoids filling of the ellipse Chris@32: Chris@32: // Set the initial color value to colorGroup().light() (bright) and start Chris@32: // drawing the shadow border at 45° (45*16 = 720). Chris@32: Chris@32: int angle = -720; Chris@32: color = palette().light().color(); Chris@32: Chris@32: for (int arc = 120; arc < 2880; arc += 240) { Chris@32: pen.setColor(color); Chris@32: paint.setPen(pen); Chris@32: int w = width - pen.width()/2 - scale + 1; Chris@32: paint.drawArc(pen.width()/2, pen.width()/2, w, w, angle + arc, 240); Chris@32: paint.drawArc(pen.width()/2, pen.width()/2, w, w, angle - arc, 240); Chris@32: color = color.dark(110); //FIXME: this should somehow use the contrast value Chris@32: } // end for ( angle = 720; angle < 6480; angle += 160 ) Chris@32: Chris@32: paint.end(); Chris@32: // Chris@32: // painting done Chris@32: Chris@32: if (smooth) { Chris@32: QPixmap *&dest = led_state ? d->on_map : d->off_map; Chris@32: QImage i = tmpMap->toImage(); Chris@32: width /= 3; Chris@32: i = i.scaled(width, width, Chris@32: Qt::IgnoreAspectRatio, Qt::SmoothTransformation); Chris@32: delete tmpMap; Chris@32: dest = new QPixmap(QPixmap::fromImage(i)); Chris@32: paint.begin(this); Chris@32: paint.drawPixmap(0, 0, *dest); Chris@32: paint.end(); Chris@32: } Chris@32: } Chris@32: Chris@32: LEDButton::State Chris@32: LEDButton::state() const Chris@32: { Chris@32: return led_state; Chris@32: } Chris@32: Chris@32: QColor Chris@32: LEDButton::color() const Chris@32: { Chris@32: return led_color; Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::setState( State state ) Chris@32: { Chris@32: if (led_state != state) Chris@32: { Chris@32: led_state = state; Chris@32: update(); Chris@32: } Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::toggleState() Chris@32: { Chris@32: led_state = (led_state == On) ? Off : On; Chris@32: // setColor(led_color); Chris@32: update(); Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::setColor(const QColor& col) Chris@32: { Chris@32: if(led_color!=col) { Chris@32: led_color = col; Chris@32: d->offcolor = col.dark(d->dark_factor); Chris@32: delete d->on_map; Chris@32: d->on_map = 0; Chris@32: delete d->off_map; Chris@32: d->off_map = 0; Chris@32: update(); Chris@32: } Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::setDarkFactor(int darkfactor) Chris@32: { Chris@32: if (d->dark_factor != darkfactor) { Chris@32: d->dark_factor = darkfactor; Chris@32: d->offcolor = led_color.dark(darkfactor); Chris@32: update(); Chris@32: } Chris@32: } Chris@32: Chris@32: int Chris@32: LEDButton::darkFactor() const Chris@32: { Chris@32: return d->dark_factor; Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::toggle() Chris@32: { Chris@32: toggleState(); Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::on() Chris@32: { Chris@32: setState(On); Chris@32: } Chris@32: Chris@32: void Chris@32: LEDButton::off() Chris@32: { Chris@32: setState(Off); Chris@32: } Chris@32: Chris@32: QSize Chris@32: LEDButton::sizeHint() const Chris@32: { Chris@32: return QSize(16, 16); Chris@32: } Chris@32: Chris@32: QSize Chris@32: LEDButton::minimumSizeHint() const Chris@32: { Chris@32: return QSize(16, 16 ); Chris@32: } Chris@32: