annotate widgets/LEDButton.cpp @ 378:22b72f0f6a4e

* More work to abstract out interactive components used in the data library, so that it does not need to depend on QtGui.
author Chris Cannam
date Fri, 14 Mar 2008 17:14:21 +0000
parents 5b7472db612b
children d01f2e406cc5
rev   line source
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@34 97 std::cerr << "LEDButton(" << this << ")::mousePressEvent" << std::endl;
Chris@34 98
Chris@33 99 if (e->buttons() & Qt::LeftButton) {
Chris@33 100 toggle();
Chris@34 101 bool newState = state();
Chris@34 102 std::cerr << "emitting new state " << newState << std::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@34 142 paint.begin(this);
Chris@34 143 paint.drawPixmap(0, 0, *d->on_map);
Chris@34 144 paint.end();
Chris@34 145 return;
Chris@34 146 }
Chris@34 147 } else {
Chris@34 148 if (d->off_map) {
Chris@34 149 paint.begin(this);
Chris@34 150 paint.drawPixmap(0, 0, *d->off_map);
Chris@34 151 paint.end();
Chris@34 152 return;
Chris@34 153 }
Chris@34 154 }
Chris@32 155
Chris@32 156 int scale = 1;
Chris@34 157 width *= scale;
Chris@32 158
Chris@34 159 tmpMap = new QPixmap(width, width);
Chris@34 160 tmpMap->fill(palette().background().color());
Chris@34 161 paint.begin(tmpMap);
Chris@32 162
Chris@33 163 paint.setRenderHint(QPainter::Antialiasing, true);
Chris@32 164
Chris@32 165 // Set the color of the LED according to given parameters
Chris@32 166 color = (led_state) ? led_color : d->offcolor;
Chris@32 167
Chris@32 168 // Set the brush to SolidPattern, this fills the entire area
Chris@32 169 // of the ellipse which is drawn first
Chris@32 170 brush.setStyle(Qt::SolidPattern);
Chris@32 171 brush.setColor(color);
Chris@32 172 paint.setBrush(brush);
Chris@32 173
Chris@32 174 // Draws a "flat" LED with the given color:
Chris@32 175 paint.drawEllipse( scale, scale, width - scale*2, width - scale*2 );
Chris@32 176
Chris@32 177 // Draw the bright light spot of the LED now, using modified "old"
Chris@32 178 // painter routine taken from KDEUI´s LEDButton widget:
Chris@32 179
Chris@32 180 // Setting the new width of the pen is essential to avoid "pixelized"
Chris@32 181 // shadow like it can be observed with the old LED code
Chris@32 182 pen.setWidth( 2 * scale );
Chris@32 183
Chris@32 184 // shrink the light on the LED to a size about 2/3 of the complete LED
Chris@32 185 int pos = width/5 + 1;
Chris@32 186 int light_width = width;
Chris@32 187 light_width *= 2;
Chris@32 188 light_width /= 3;
Chris@32 189
Chris@32 190 // Calculate the LED´s "light factor":
Chris@32 191 int light_quote = (130*2/(light_width?light_width:1))+100;
Chris@32 192
Chris@32 193 // Now draw the bright spot on the LED:
Chris@32 194 while (light_width) {
Chris@32 195 color = color.light( light_quote ); // make color lighter
Chris@32 196 pen.setColor( color ); // set color as pen color
Chris@32 197 paint.setPen( pen ); // select the pen for drawing
Chris@32 198 paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle)
Chris@32 199 light_width--;
Chris@32 200 if (!light_width)
Chris@32 201 break;
Chris@32 202 paint.drawEllipse( pos, pos, light_width, light_width );
Chris@32 203 light_width--;
Chris@32 204 if (!light_width)
Chris@32 205 break;
Chris@32 206 paint.drawEllipse( pos, pos, light_width, light_width );
Chris@32 207 pos++; light_width--;
Chris@32 208 }
Chris@32 209
Chris@32 210 // Drawing of bright spot finished, now draw a thin border
Chris@32 211 // around the LED which resembles a shadow with light coming
Chris@32 212 // from the upper left.
Chris@32 213
Chris@33 214 // pen.setWidth( 2 * scale + 1 ); // ### shouldn't this value be smaller for smaller LEDs?
Chris@33 215 pen.setWidth(2 * scale);
Chris@32 216 brush.setStyle(Qt::NoBrush);
Chris@32 217 paint.setBrush(brush); // This avoids filling of the ellipse
Chris@32 218
Chris@32 219 // Set the initial color value to colorGroup().light() (bright) and start
Chris@32 220 // drawing the shadow border at 45° (45*16 = 720).
Chris@32 221
Chris@32 222 int angle = -720;
Chris@32 223 color = palette().light().color();
Chris@32 224
Chris@32 225 for (int arc = 120; arc < 2880; arc += 240) {
Chris@32 226 pen.setColor(color);
Chris@32 227 paint.setPen(pen);
Chris@32 228 int w = width - pen.width()/2 - scale + 1;
Chris@33 229 paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle + arc, 240);
Chris@33 230 paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle - arc, 240);
Chris@32 231 color = color.dark(110); //FIXME: this should somehow use the contrast value
Chris@32 232 } // end for ( angle = 720; angle < 6480; angle += 160 )
Chris@32 233
Chris@32 234 paint.end();
Chris@32 235 //
Chris@32 236 // painting done
Chris@32 237
Chris@34 238 QPixmap *&dest = led_state ? d->on_map : d->off_map;
Chris@34 239
Chris@34 240 if (scale > 1) {
Chris@34 241
Chris@32 242 QImage i = tmpMap->toImage();
Chris@33 243 width /= scale;
Chris@32 244 delete tmpMap;
Chris@33 245 dest = new QPixmap(QPixmap::fromImage
Chris@33 246 (i.scaled(width, width,
Chris@33 247 Qt::KeepAspectRatio,
Chris@33 248 Qt::SmoothTransformation)));
Chris@34 249
Chris@34 250 } else {
Chris@34 251
Chris@34 252 dest = tmpMap;
Chris@32 253 }
Chris@34 254
Chris@34 255 paint.begin(this);
Chris@34 256 paint.drawPixmap(0, 0, *dest);
Chris@34 257 paint.end();
Chris@32 258 }
Chris@32 259
Chris@34 260 bool
Chris@32 261 LEDButton::state() const
Chris@32 262 {
Chris@32 263 return led_state;
Chris@32 264 }
Chris@32 265
Chris@32 266 QColor
Chris@32 267 LEDButton::color() const
Chris@32 268 {
Chris@32 269 return led_color;
Chris@32 270 }
Chris@32 271
Chris@32 272 void
Chris@34 273 LEDButton::setState( bool state )
Chris@32 274 {
Chris@32 275 if (led_state != state)
Chris@32 276 {
Chris@32 277 led_state = state;
Chris@32 278 update();
Chris@32 279 }
Chris@32 280 }
Chris@32 281
Chris@32 282 void
Chris@32 283 LEDButton::toggleState()
Chris@32 284 {
Chris@34 285 led_state = (led_state == true) ? false : true;
Chris@32 286 // setColor(led_color);
Chris@32 287 update();
Chris@32 288 }
Chris@32 289
Chris@32 290 void
Chris@32 291 LEDButton::setColor(const QColor& col)
Chris@32 292 {
Chris@32 293 if(led_color!=col) {
Chris@32 294 led_color = col;
Chris@32 295 d->offcolor = col.dark(d->dark_factor);
Chris@32 296 delete d->on_map;
Chris@32 297 d->on_map = 0;
Chris@32 298 delete d->off_map;
Chris@32 299 d->off_map = 0;
Chris@32 300 update();
Chris@32 301 }
Chris@32 302 }
Chris@32 303
Chris@32 304 void
Chris@32 305 LEDButton::setDarkFactor(int darkfactor)
Chris@32 306 {
Chris@32 307 if (d->dark_factor != darkfactor) {
Chris@32 308 d->dark_factor = darkfactor;
Chris@32 309 d->offcolor = led_color.dark(darkfactor);
Chris@32 310 update();
Chris@32 311 }
Chris@32 312 }
Chris@32 313
Chris@32 314 int
Chris@32 315 LEDButton::darkFactor() const
Chris@32 316 {
Chris@32 317 return d->dark_factor;
Chris@32 318 }
Chris@32 319
Chris@32 320 void
Chris@32 321 LEDButton::toggle()
Chris@32 322 {
Chris@32 323 toggleState();
Chris@32 324 }
Chris@32 325
Chris@32 326 void
Chris@32 327 LEDButton::on()
Chris@32 328 {
Chris@34 329 setState(true);
Chris@32 330 }
Chris@32 331
Chris@32 332 void
Chris@32 333 LEDButton::off()
Chris@32 334 {
Chris@34 335 setState(false);
Chris@32 336 }
Chris@32 337
Chris@32 338 QSize
Chris@32 339 LEDButton::sizeHint() const
Chris@32 340 {
Chris@33 341 return QSize(17, 17);
Chris@32 342 }
Chris@32 343
Chris@32 344 QSize
Chris@32 345 LEDButton::minimumSizeHint() const
Chris@32 346 {
Chris@33 347 return QSize(17, 17);
Chris@32 348 }
Chris@32 349