~ubuntu-branches/ubuntu/natty/kdemultimedia/natty-proposed

« back to all changes in this revision

Viewing changes to kmix/gui/ksmallslider.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Debian Qt/KDE Maintainers
  • Date: 2011-05-26 02:41:36 UTC
  • mfrom: (0.2.3 upstream)
  • mto: This revision was merged to the branch mainline in revision 108.
  • Revision ID: james.westby@ubuntu.com-20110526024136-jjwsigfy402jhupm
Tags: upstream-4.6.3
ImportĀ upstreamĀ versionĀ 4.6.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * KMix -- KDE's full featured mini mixer
 
3
 *
 
4
 *
 
5
 * Copyright (C) 2000 Stefan Schimanski <1Stein@gmx.de>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Library General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Library General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Library General Public
 
18
 * License along with this program; if not, write to the Free
 
19
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
20
 */
 
21
 
 
22
// For INT_MAX
 
23
#include <limits.h>
 
24
 
 
25
#include <kdebug.h>
 
26
 
 
27
#include <QWidget>
 
28
#include <qpainter.h>
 
29
#include <QColor>
 
30
#include <qbrush.h>
 
31
#include <QMouseEvent>
 
32
#include <qstyle.h>
 
33
#include <QStyleOptionSlider>
 
34
 
 
35
#include "kglobalsettings.h"
 
36
#include "ksmallslider.h"
 
37
 
 
38
KSmallSlider::KSmallSlider( int minValue, int maxValue, int pageStep,
 
39
                  int value, Qt::Orientation orientation,
 
40
                  QWidget *parent, const char * /*name*/ )
 
41
    : QAbstractSlider( parent )
 
42
{
 
43
    init();
 
44
    setOrientation(orientation);
 
45
    setRange(minValue, maxValue);
 
46
    setSingleStep(1);
 
47
    setPageStep(pageStep);
 
48
    setValue(value);
 
49
         setTracking(true);
 
50
}
 
51
 
 
52
void KSmallSlider::init()
 
53
{
 
54
    grayed = false;
 
55
    setFocusPolicy( Qt::TabFocus  );
 
56
 
 
57
    colHigh = QColor(0,255,0);
 
58
    colLow = QColor(255,0,0);
 
59
    colBack = QColor(0,0,0);
 
60
 
 
61
    grayHigh = QColor(255,255,255);
 
62
    grayLow = QColor(128,128,128);
 
63
    grayBack = QColor(0,0,0);
 
64
}
 
65
 
 
66
int KSmallSlider::positionFromValue( int v ) const
 
67
{
 
68
    return positionFromValue( v, available() );
 
69
}
 
70
 
 
71
int KSmallSlider::valueFromPosition( int p ) const
 
72
{
 
73
    if ( orientation() == Qt::Vertical ) {
 
74
        // Coordiante System starts at TopLeft, but the slider values increase from Bottom to Top
 
75
        // Thus "revert" the position
 
76
        int avail = available();
 
77
        return valueFromPosition( avail - p, avail );
 
78
    }
 
79
    else {
 
80
        // Horizontal everything is fine. Slider values match with Coordinate System
 
81
        return valueFromPosition( p, available() );
 
82
    }
 
83
}
 
84
 
 
85
/*  postionFromValue() discontinued in in Qt4 => taken from Qt3 */
 
86
int KSmallSlider::positionFromValue( int logical_val, int span ) const
 
87
{
 
88
    if ( span <= 0 || logical_val < minimum() || maximum() <= minimum() )
 
89
        return 0;
 
90
    if ( logical_val > maximum() )
 
91
        return span;
 
92
 
 
93
    uint range = maximum() - minimum();
 
94
    uint p = logical_val - minimum();
 
95
 
 
96
    if ( range > (uint)INT_MAX/4096 ) {
 
97
        const int scale = 4096*2;
 
98
        return ( (p/scale) * span ) / (range/scale);
 
99
        // ### the above line is probably not 100% correct
 
100
        // ### but fixing it isn't worth the extreme pain...
 
101
    } else if ( range > (uint)span ) {
 
102
        return (2*p*span + range) / (2*range);
 
103
    } else {
 
104
        uint div = span / range;
 
105
        uint mod = span % range;
 
106
        return p*div + (2*p*mod + range) / (2*range);
 
107
    }
 
108
    //equiv. to (p*span)/range + 0.5
 
109
    // no overflow because of this implicit assumption:
 
110
    // span <= 4096
 
111
}
 
112
 
 
113
/* valueFromPositon() discontinued in in Qt4 => taken from Qt3 */
 
114
int KSmallSlider::valueFromPosition( int pos, int span ) const
 
115
{
 
116
    if ( span <= 0 || pos <= 0 )
 
117
        return minimum();
 
118
    if ( pos >= span )
 
119
        return maximum();
 
120
 
 
121
    uint range = maximum() - minimum();
 
122
 
 
123
    if ( (uint)span > range )
 
124
        return  minimum() + (2*pos*range + span) / (2*span);
 
125
    else {
 
126
        uint div = range / span;
 
127
        uint mod = range % span;
 
128
        return  minimum() + pos*div + (2*pos*mod + span) / (2*span);
 
129
    }
 
130
    // equiv. to minimum() + (pos*range)/span + 0.5
 
131
    // no overflow because of this implicit assumption:
 
132
    // pos <= span < sqrt(INT_MAX+0.0625)+0.25 ~ sqrt(INT_MAX)
 
133
}
 
134
 
 
135
 
 
136
void KSmallSlider::resizeEvent( QResizeEvent * )
 
137
{
 
138
    update();
 
139
    //QWidget::resizeEvent( ev );
 
140
}
 
141
 
 
142
//  Returns the really available space for the slider. If there is no space, 0 is returned;
 
143
int KSmallSlider::available() const
 
144
{
 
145
    int available = 0;
 
146
    if ( orientation() == Qt::Vertical) {
 
147
        available = height();
 
148
    }
 
149
    else {
 
150
        available = width();
 
151
    }
 
152
    if ( available > 1 ) {
 
153
        available -= 2;
 
154
    }
 
155
    else {
 
156
        available = 0;
 
157
    }
 
158
    return available;
 
159
}
 
160
 
 
161
 
 
162
 
 
163
namespace
 
164
{
 
165
 
 
166
void gradient( QPainter &p, bool hor, const QRect &rect, const QColor &ca, const QColor &cb, int /*ncols*/)
 
167
{
 
168
   int rDiff, gDiff, bDiff;
 
169
   int rca, gca, bca, rcb, gcb, bcb;
 
170
 
 
171
   register int x, y;
 
172
 
 
173
   if ((rect.width()<=0) || (rect.height()<=0)) return;
 
174
 
 
175
   rDiff = (rcb = cb.red())   - (rca = ca.red());
 
176
   gDiff = (gcb = cb.green()) - (gca = ca.green());
 
177
   bDiff = (bcb = cb.blue())  - (bca = ca.blue());
 
178
 
 
179
   register int rl = rca << 16;
 
180
   register int gl = gca << 16;
 
181
   register int bl = bca << 16;
 
182
 
 
183
   int rcdelta = ((1<<16) / ((!hor) ? rect.height() : rect.width())) * rDiff;
 
184
   int gcdelta = ((1<<16) / ((!hor) ? rect.height() : rect.width())) * gDiff;
 
185
   int bcdelta = ((1<<16) / ((!hor) ? rect.height() : rect.width())) * bDiff;
 
186
 
 
187
   // these for-loops could be merged, but the if's in the inner loop
 
188
   // would make it slow
 
189
   if (!hor)
 
190
   {
 
191
      for ( y = rect.top(); y <= rect.bottom(); y++ ) {
 
192
         rl += rcdelta;
 
193
         gl += gcdelta;
 
194
         bl += bcdelta;
 
195
 
 
196
         p.setPen(QColor(rl>>16, gl>>16, bl>>16));
 
197
         p.drawLine(rect.left(), y, rect.right(), y);
 
198
      }
 
199
   } else
 
200
   {
 
201
      for( x = rect.left(); x <= rect.right(); x++) {
 
202
         rl += rcdelta;
 
203
         gl += gcdelta;
 
204
         bl += bcdelta;
 
205
 
 
206
         p.setPen(QColor(rl>>16, gl>>16, bl>>16));
 
207
         p.drawLine(x, rect.top(), x, rect.bottom());
 
208
      }
 
209
   }
 
210
}
 
211
 
 
212
QColor interpolate( const QColor& low, const QColor& high, int percent ) {
 
213
    if ( percent<=0 ) return low; else
 
214
    if ( percent>=100 ) return high; else
 
215
    return QColor(
 
216
        low.red() + (high.red()-low.red()) * percent/100,
 
217
        low.green() + (high.green()-low.green()) * percent/100,
 
218
        low.blue() + (high.blue()-low.blue()) * percent/100 );
 
219
}
 
220
 
 
221
}
 
222
 
 
223
void KSmallSlider::paintEvent( QPaintEvent * )
 
224
{
 
225
//    kDebug(67100) << "KSmallSlider::paintEvent: width() = " << width() << ", height() = " << height();
 
226
   QPainter p( this );
 
227
 
 
228
   int sliderPos = positionFromValue( QAbstractSlider::value() );
 
229
 
 
230
   // ------------------------ draw 3d border ---------------------------------------------
 
231
   QStyleOptionSlider option;
 
232
   option.init(this);
 
233
   style()->drawPrimitive ( QStyle::PE_Frame, &option, &p );
 
234
 
 
235
 
 
236
   // ------------------------ draw lower/left part ----------------------------------------
 
237
   if ( width()>2 && height()>2 )
 
238
   {
 
239
       if (  orientation() == Qt::Horizontal ) {
 
240
         QRect outer = QRect( 1, 1, sliderPos, height() - 2 );
 
241
//       kDebug(67100) << "KSmallSlider::paintEvent: outer = " << outer;
 
242
 
 
243
         if ( grayed )
 
244
             gradient( p, true, outer, grayLow,
 
245
                       interpolate( grayLow, grayHigh, 100*sliderPos/(width()-2) ),
 
246
                       32 );
 
247
         else
 
248
             gradient( p, true, outer, colLow,
 
249
                       interpolate( colLow, colHigh, 100*sliderPos/(width()-2) ),
 
250
                       32 );
 
251
      }
 
252
      else {
 
253
         QRect outer = QRect( 1, height()-sliderPos-1, width() - 2, sliderPos-1 );
 
254
/*
 
255
         kDebug(67100) << "KSmallSlider::paintEvent: sliderPos=" << sliderPos
 
256
                        << "height()=" << height()
 
257
                        << "width()=" << width()
 
258
                        << "outer = " << outer << endl;
 
259
*/
 
260
         if ( grayed )
 
261
             gradient( p, false, outer,
 
262
                       interpolate( grayLow, grayHigh, 100*sliderPos/(height()-2) ),
 
263
                       grayLow, 32 );
 
264
         else
 
265
             gradient( p, false, outer,
 
266
                       interpolate( colLow, colHigh, 100*sliderPos/(height()-2) ),
 
267
                       colLow, 32 );
 
268
      }
 
269
 
 
270
      // -------- draw upper/right part --------------------------------------------------
 
271
      QRect inner;
 
272
      if ( orientation() == Qt::Vertical ) {
 
273
          inner = QRect( 1, 1, width() - 2, height() - 2 -sliderPos );
 
274
      }
 
275
      else {
 
276
          inner = QRect( sliderPos + 1, 1, width() - 2 - sliderPos, height() - 2 );
 
277
      }
 
278
        
 
279
      if ( grayed ) {
 
280
          p.setBrush( grayBack );
 
281
          p.setPen( grayBack );
 
282
      } else {
 
283
          p.setBrush( colBack );
 
284
          p.setPen( colBack );
 
285
      }
 
286
      p.drawRect( inner );
 
287
   }
 
288
}
 
289
 
 
290
void KSmallSlider::mousePressEvent( QMouseEvent *e )
 
291
{
 
292
    //resetState();
 
293
 
 
294
   if ( e->button() == Qt::RightButton ) {
 
295
      return;
 
296
   }
 
297
 
 
298
   int pos = goodPart( e->pos() );
 
299
   moveSlider( pos );
 
300
}
 
301
 
 
302
void KSmallSlider::mouseMoveEvent( QMouseEvent *e )
 
303
{
 
304
    int pos = goodPart( e->pos() );
 
305
    moveSlider( pos );
 
306
}
 
307
 
 
308
/*
 
309
void KSmallSlider::wheelEvent( QWheelEvent * e)
 
310
{
 
311
//    kDebug(67100) << "KSmallslider::wheelEvent()";
 
312
    int inc = ( maximum() - minimum() ) / 20;
 
313
    if ( inc < 1)
 
314
        inc = 1;
 
315
 
 
316
    //kDebug(67100) << "KSmallslider::wheelEvent() inc=" << inc << "delta=" << e->delta();
 
317
    if ( e->delta() > 0 ) {
 
318
       setValue( QAbstractSlider::value() + inc );
 
319
    }
 
320
    else {
 
321
       setValue( QAbstractSlider::value() - inc );
 
322
    }
 
323
    e->accept(); // Accept the event
 
324
 
 
325
    // Hint: Qt autmatically triggers a valueChange() when we do setValue()
 
326
}
 
327
*/
 
328
 
 
329
 
 
330
/*
 
331
 * Moves slider to a dedicated position. If the value has changed
 
332
 */
 
333
void KSmallSlider::moveSlider( int pos )
 
334
{
 
335
    int  a = available();
 
336
    int newPos = qMin( a, qMax( 0, pos ) );  // keep it inside the available bounds of the slider
 
337
    int newVal = valueFromPosition( newPos );
 
338
 
 
339
    if ( newVal != value() ) {
 
340
        setValue( newVal );
 
341
        // probably done by Qt: emit valueChanged( value() ); //  Only for external use
 
342
        // probably we need update() here
 
343
    }
 
344
    update();
 
345
}
 
346
 
 
347
 
 
348
int KSmallSlider::goodPart( const QPoint &p ) const
 
349
{
 
350
    if ( orientation() == Qt::Vertical ) {
 
351
        return p.y() - 1;
 
352
    }
 
353
    else {
 
354
        return p.x() - 1;
 
355
    }
 
356
}
 
357
 
 
358
/***************** SIZE STUFF START ***************/
 
359
QSize KSmallSlider::sizeHint() const
 
360
{
 
361
    //constPolish();
 
362
    const int length = 25;
 
363
    const int thick  = 10;
 
364
 
 
365
    if (  orientation() == Qt::Vertical )
 
366
        return QSize( thick, length );
 
367
    else
 
368
        return QSize( length, thick );
 
369
}
 
370
 
 
371
 
 
372
QSize KSmallSlider::minimumSizeHint() const
 
373
{
 
374
    QSize s(10,10);
 
375
    return s;
 
376
}
 
377
 
 
378
 
 
379
QSizePolicy KSmallSlider::sizePolicy() const
 
380
{
 
381
 
 
382
    if ( orientation() == Qt::Vertical ) {
 
383
        //kDebug(67100) << "KSmallSlider::sizePolicy() vertical value=(Fixed,MinimumExpanding)\n";
 
384
        return QSizePolicy(  QSizePolicy::Fixed, QSizePolicy::Expanding );
 
385
    }
 
386
    else {
 
387
        //kDebug(67100) << "KSmallSlider::sizePolicy() horizontal value=(MinimumExpanding,Fixed)\n";
 
388
        return QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
 
389
    }
 
390
}
 
391
/***************** SIZE STUFF END ***************/
 
392
 
 
393
 
 
394
 
 
395
void KSmallSlider::setGray( bool value )
 
396
{
 
397
   if ( grayed!=value )
 
398
   {
 
399
      grayed = value;
 
400
      update();
 
401
      //repaint();
 
402
   }
 
403
}
 
404
 
 
405
bool KSmallSlider::gray() const
 
406
{
 
407
   return grayed;
 
408
}
 
409
 
 
410
void KSmallSlider::setColors( QColor high, QColor low, QColor back )
 
411
{
 
412
    colHigh = high;
 
413
    colLow = low;
 
414
    colBack = back;
 
415
    update();
 
416
    //repaint();
 
417
}
 
418
 
 
419
void KSmallSlider::setGrayColors( QColor high, QColor low, QColor back )
 
420
{
 
421
    grayHigh = high;
 
422
    grayLow = low;
 
423
    grayBack = back;
 
424
    update();
 
425
    //repaint();
 
426
}
 
427
 
 
428
#include "ksmallslider.moc"