annotate widgets/LEDButton.cpp @ 1025:c02de0e34233 spectrogram-minor-refactor

Make paint method do its own timing and abandon if it's taking too long (still needs some work on queueing correct repaints of the remainder)
author Chris Cannam
date Mon, 25 Jan 2016 16:16:21 +0000
parents e8949ccb4f4e
children 3f5c82034f9b
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 };
Chris@32 42
Chris@32 43
Chris@32 44 LEDButton::LEDButton(QWidget *parent) :
Chris@32 45 QWidget(parent),
Chris@34 46 led_state(true)
Chris@32 47 {
Chris@32 48 QColor col(Qt::green);
Chris@32 49 d = new LEDButton::LEDButtonPrivate;
Chris@32 50 d->dark_factor = 300;
Chris@32 51 d->offcolor = col.dark(300);
Chris@32 52
Chris@32 53 setColor(col);
Chris@32 54 }
Chris@32 55
Chris@32 56
Chris@32 57 LEDButton::LEDButton(const QColor& col, QWidget *parent) :
Chris@32 58 QWidget(parent),
Chris@34 59 led_state(true)
Chris@32 60 {
Chris@32 61 d = new LEDButton::LEDButtonPrivate;
Chris@32 62 d->dark_factor = 300;
Chris@32 63 d->offcolor = col.dark(300);
Chris@32 64
Chris@32 65 setColor(col);
Chris@32 66 }
Chris@32 67
Chris@34 68 LEDButton::LEDButton(const QColor& col, bool state, QWidget *parent) :
Chris@32 69 QWidget(parent),
Chris@32 70 led_state(state)
Chris@32 71 {
Chris@32 72 d = new LEDButton::LEDButtonPrivate;
Chris@32 73 d->dark_factor = 300;
Chris@32 74 d->offcolor = col.dark(300);
Chris@32 75
Chris@32 76 setColor(col);
Chris@32 77 }
Chris@32 78
Chris@32 79 LEDButton::~LEDButton()
Chris@32 80 {
Chris@32 81 delete d;
Chris@32 82 }
Chris@32 83
Chris@32 84 void
Chris@33 85 LEDButton::mousePressEvent(QMouseEvent *e)
Chris@33 86 {
Chris@682 87 cerr << "LEDButton(" << this << ")::mousePressEvent" << endl;
Chris@34 88
Chris@33 89 if (e->buttons() & Qt::LeftButton) {
Chris@33 90 toggle();
Chris@34 91 bool newState = state();
Chris@587 92 SVDEBUG << "emitting new state " << newState << endl;
Chris@34 93 emit stateChanged(newState);
Chris@33 94 }
Chris@33 95 }
Chris@33 96
Chris@33 97 void
Chris@189 98 LEDButton::enterEvent(QEvent *)
Chris@189 99 {
Chris@189 100 emit mouseEntered();
Chris@189 101 }
Chris@189 102
Chris@189 103 void
Chris@189 104 LEDButton::leaveEvent(QEvent *)
Chris@189 105 {
Chris@189 106 emit mouseLeft();
Chris@189 107 }
Chris@189 108
Chris@189 109 void
Chris@32 110 LEDButton::paintEvent(QPaintEvent *)
Chris@32 111 {
Chris@32 112 QPainter paint;
Chris@32 113 QColor color;
Chris@32 114 QBrush brush;
Chris@32 115 QPen pen;
Chris@32 116
Chris@32 117 // First of all we want to know what area should be updated
Chris@32 118 // Initialize coordinates, width, and height of the LED
Chris@32 119 int width = this->width();
Chris@32 120
Chris@32 121 // Make sure the LED is round!
Chris@32 122 if (width > this->height())
Chris@32 123 width = this->height();
Chris@32 124 width -= 2; // leave one pixel border
Chris@32 125 if (width < 0)
Chris@32 126 width = 0;
Chris@32 127
Chris@983 128 paint.begin(this);
Chris@32 129
Chris@33 130 paint.setRenderHint(QPainter::Antialiasing, true);
Chris@32 131
Chris@32 132 // Set the color of the LED according to given parameters
Chris@32 133 color = (led_state) ? led_color : d->offcolor;
Chris@32 134
Chris@32 135 // Set the brush to SolidPattern, this fills the entire area
Chris@32 136 // of the ellipse which is drawn first
Chris@32 137 brush.setStyle(Qt::SolidPattern);
Chris@32 138 brush.setColor(color);
Chris@32 139 paint.setBrush(brush);
Chris@32 140
Chris@32 141 // Draws a "flat" LED with the given color:
Chris@983 142 paint.drawEllipse( 1, 1, width - 2, width - 2 );
Chris@32 143
Chris@32 144 // Draw the bright light spot of the LED now, using modified "old"
Chris@32 145 // painter routine taken from KDEUI´s LEDButton widget:
Chris@32 146
Chris@32 147 // Setting the new width of the pen is essential to avoid "pixelized"
Chris@32 148 // shadow like it can be observed with the old LED code
Chris@983 149 pen.setWidth( 2 );
Chris@32 150
Chris@32 151 // shrink the light on the LED to a size about 2/3 of the complete LED
Chris@32 152 int pos = width/5 + 1;
Chris@32 153 int light_width = width;
Chris@32 154 light_width *= 2;
Chris@32 155 light_width /= 3;
Chris@32 156
Chris@32 157 // Calculate the LED´s "light factor":
Chris@32 158 int light_quote = (130*2/(light_width?light_width:1))+100;
Chris@32 159
Chris@32 160 // Now draw the bright spot on the LED:
Chris@32 161 while (light_width) {
Chris@32 162 color = color.light( light_quote ); // make color lighter
Chris@32 163 pen.setColor( color ); // set color as pen color
Chris@32 164 paint.setPen( pen ); // select the pen for drawing
Chris@32 165 paint.drawEllipse( pos, pos, light_width, light_width ); // draw the ellipse (circle)
Chris@32 166 light_width--;
Chris@32 167 if (!light_width)
Chris@32 168 break;
Chris@32 169 paint.drawEllipse( pos, pos, light_width, light_width );
Chris@32 170 light_width--;
Chris@32 171 if (!light_width)
Chris@32 172 break;
Chris@32 173 paint.drawEllipse( pos, pos, light_width, light_width );
Chris@32 174 pos++; light_width--;
Chris@32 175 }
Chris@32 176
Chris@984 177 paint.drawPoint(pos, pos);
Chris@984 178
Chris@32 179 // Drawing of bright spot finished, now draw a thin border
Chris@32 180 // around the LED which resembles a shadow with light coming
Chris@32 181 // from the upper left.
Chris@32 182
Chris@983 183 pen.setWidth(2);
Chris@32 184 brush.setStyle(Qt::NoBrush);
Chris@32 185 paint.setBrush(brush); // This avoids filling of the ellipse
Chris@32 186
Chris@32 187 // Set the initial color value to colorGroup().light() (bright) and start
Chris@32 188 // drawing the shadow border at 45° (45*16 = 720).
Chris@32 189
Chris@32 190 int angle = -720;
Chris@32 191 color = palette().light().color();
Chris@32 192
Chris@32 193 for (int arc = 120; arc < 2880; arc += 240) {
Chris@32 194 pen.setColor(color);
Chris@32 195 paint.setPen(pen);
Chris@983 196 int w = width - pen.width()/2;
Chris@33 197 paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle + arc, 240);
Chris@33 198 paint.drawArc(pen.width()/2 + 1, pen.width()/2 + 1, w - 2, w - 2, angle - arc, 240);
Chris@32 199 color = color.dark(110); //FIXME: this should somehow use the contrast value
Chris@32 200 } // end for ( angle = 720; angle < 6480; angle += 160 )
Chris@32 201
Chris@32 202 paint.end();
Chris@32 203 }
Chris@32 204
Chris@34 205 bool
Chris@32 206 LEDButton::state() const
Chris@32 207 {
Chris@32 208 return led_state;
Chris@32 209 }
Chris@32 210
Chris@32 211 QColor
Chris@32 212 LEDButton::color() const
Chris@32 213 {
Chris@32 214 return led_color;
Chris@32 215 }
Chris@32 216
Chris@32 217 void
Chris@34 218 LEDButton::setState( bool state )
Chris@32 219 {
Chris@32 220 if (led_state != state)
Chris@32 221 {
Chris@32 222 led_state = state;
Chris@32 223 update();
Chris@32 224 }
Chris@32 225 }
Chris@32 226
Chris@32 227 void
Chris@32 228 LEDButton::toggleState()
Chris@32 229 {
Chris@34 230 led_state = (led_state == true) ? false : true;
Chris@32 231 // setColor(led_color);
Chris@32 232 update();
Chris@32 233 }
Chris@32 234
Chris@32 235 void
Chris@32 236 LEDButton::setColor(const QColor& col)
Chris@32 237 {
Chris@32 238 if(led_color!=col) {
Chris@32 239 led_color = col;
Chris@32 240 d->offcolor = col.dark(d->dark_factor);
Chris@32 241 update();
Chris@32 242 }
Chris@32 243 }
Chris@32 244
Chris@32 245 void
Chris@32 246 LEDButton::setDarkFactor(int darkfactor)
Chris@32 247 {
Chris@32 248 if (d->dark_factor != darkfactor) {
Chris@32 249 d->dark_factor = darkfactor;
Chris@32 250 d->offcolor = led_color.dark(darkfactor);
Chris@32 251 update();
Chris@32 252 }
Chris@32 253 }
Chris@32 254
Chris@32 255 int
Chris@32 256 LEDButton::darkFactor() const
Chris@32 257 {
Chris@32 258 return d->dark_factor;
Chris@32 259 }
Chris@32 260
Chris@32 261 void
Chris@32 262 LEDButton::toggle()
Chris@32 263 {
Chris@32 264 toggleState();
Chris@32 265 }
Chris@32 266
Chris@32 267 void
Chris@32 268 LEDButton::on()
Chris@32 269 {
Chris@34 270 setState(true);
Chris@32 271 }
Chris@32 272
Chris@32 273 void
Chris@32 274 LEDButton::off()
Chris@32 275 {
Chris@34 276 setState(false);
Chris@32 277 }
Chris@32 278
Chris@32 279 QSize
Chris@32 280 LEDButton::sizeHint() const
Chris@32 281 {
Chris@33 282 return QSize(17, 17);
Chris@32 283 }
Chris@32 284
Chris@32 285 QSize
Chris@32 286 LEDButton::minimumSizeHint() const
Chris@32 287 {
Chris@33 288 return QSize(17, 17);
Chris@32 289 }
Chris@32 290