annotate widgets/LEDButton.cpp @ 282:d9319859a4cf tip

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