annotate widgets/LEDButton.cpp @ 38:beb801473743

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