~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/qt3support/widgets/q3rangecontrol.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the Qt 3 compatibility classes of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "q3rangecontrol.h"
 
30
#ifndef QT_NO_RANGECONTROL
 
31
#include "qglobal.h"
 
32
#include <limits.h>
 
33
 
 
34
/*!
 
35
    \class Q3RangeControl qrangecontrol.h
 
36
    \brief The Q3RangeControl class provides an integer value within a range.
 
37
 
 
38
    \compat
 
39
 
 
40
    Although originally designed for the QScrollBar widget, the
 
41
    Q3RangeControl can also be used in conjunction with other widgets
 
42
    such as QSlider and QSpinBox. Here are the five main concepts in
 
43
    the class:
 
44
 
 
45
    \list 1
 
46
 
 
47
    \i \e{Current value} The bounded integer that
 
48
    Q3RangeControl maintains. value() returns it, and several
 
49
    functions, including setValue(), set it.
 
50
 
 
51
    \i \e{Minimum} The lowest value that value() can ever
 
52
    return. Returned by minValue() and set by setRange() or one of the
 
53
    constructors.
 
54
 
 
55
    \i \e{Maximum} The highest value that value() can ever
 
56
    return. Returned by maxValue() and set by setRange() or one of the
 
57
    constructors.
 
58
 
 
59
    \i \e{Line step} The smaller of two natural steps that
 
60
    Q3RangeControl provides and typically corresponds to the user
 
61
    pressing an arrow key. The line step is returned by lineStep()
 
62
    and set using setSteps(). The functions addLine() and
 
63
    subtractLine() respectively increment and decrement the current
 
64
    value by lineStep().
 
65
 
 
66
    \i \e{Page step} The larger of two natural steps that
 
67
    Q3RangeControl provides and typically corresponds to the user
 
68
    pressing PageUp or PageDown. The page step is returned by
 
69
    pageStep() and set using setSteps(). The functions addPage() and
 
70
    substractPage() respectively increment and decrement the current
 
71
    value by pageStep().
 
72
 
 
73
    \endlist
 
74
 
 
75
    Unity (1) may be viewed as a third step size. setValue() lets you
 
76
    set the current value to any integer in the allowed range, not
 
77
    just minValue() + \e n * lineStep() for integer values of \e n.
 
78
    Some widgets may allow the user to set any value at all; others
 
79
    may just provide multiples of lineStep() or pageStep().
 
80
 
 
81
    Q3RangeControl provides three virtual functions that are well
 
82
    suited for updating the on-screen representation of range controls
 
83
    and emitting signals: valueChange(), rangeChange() and
 
84
    stepChange().
 
85
 
 
86
    Q3RangeControl also provides a function called bound() which lets
 
87
    you force arbitrary integers to be within the allowed range of the
 
88
    range control.
 
89
 
 
90
    We recommend that all widgets that inherit Q3RangeControl provide
 
91
    at least a signal called valueChanged(); many widgets will want to
 
92
    provide addStep(), addPage(), substractStep() and substractPage()
 
93
    as slots.
 
94
 
 
95
    Note that you must use multiple inheritance if you plan to
 
96
    implement a widget using Q3RangeControl because Q3RangeControl is
 
97
    not derived from QWidget.
 
98
*/
 
99
 
 
100
 
 
101
/*!
 
102
    Constructs a range control with a minimum value of 0, maximum
 
103
    value of 99, line step of 1, page step of 10 and initial value 0.
 
104
*/
 
105
 
 
106
Q3RangeControl::Q3RangeControl()
 
107
{
 
108
    minVal  = 0;
 
109
    maxVal  = 99;
 
110
    line    = 1;
 
111
    page    = 10;
 
112
    val            = 0;
 
113
    prevVal = -1;
 
114
    d            = 0;
 
115
}
 
116
 
 
117
/*!
 
118
    Constructs a range control whose value can never be smaller than
 
119
    \a minValue or greater than \a maxValue, whose line step size is
 
120
    \a lineStep and page step size is \a pageStep and whose value is
 
121
    initially \a value (which is guaranteed to be in range using
 
122
    bound()).
 
123
*/
 
124
 
 
125
Q3RangeControl::Q3RangeControl(int minValue, int maxValue,
 
126
                              int lineStep, int pageStep,
 
127
                              int value)
 
128
{
 
129
    minVal  = minValue;
 
130
    maxVal  = maxValue;
 
131
    line    = QABS(lineStep);
 
132
    page    = QABS(pageStep);
 
133
    prevVal = minVal - 1;
 
134
    val            = bound(value);
 
135
    d            = 0;
 
136
}
 
137
 
 
138
/*!
 
139
    Destroys the range control
 
140
*/
 
141
 
 
142
Q3RangeControl::~Q3RangeControl()
 
143
{
 
144
}
 
145
 
 
146
 
 
147
/*!
 
148
    \fn int Q3RangeControl::value() const
 
149
 
 
150
    Returns the current range control value. This is guaranteed to be
 
151
    within the range [minValue(), maxValue()].
 
152
 
 
153
    \sa setValue() prevValue()
 
154
*/
 
155
 
 
156
/*!
 
157
    \fn int Q3RangeControl::prevValue() const
 
158
 
 
159
    Returns the previous value of the range control. "Previous value"
 
160
    means the value before the last change occurred. Setting a new
 
161
    range may affect the value, too, because the value is forced to be
 
162
    inside the specified range. When the range control is initially
 
163
    created, this is the same as value().
 
164
 
 
165
    prevValue() can be outside the current legal range if a call to
 
166
    setRange() causes the current value to change. For example, if the
 
167
    range was [0, 1000] and the current value is 500, setRange(0, 400)
 
168
    makes value() return 400 and prevValue() return 500.
 
169
 
 
170
    \sa value() setRange()
 
171
*/
 
172
 
 
173
/*!
 
174
    Sets the range control's value to \a value and forces it to be
 
175
    within the legal range.
 
176
 
 
177
    Calls the virtual valueChange() function if the new value is
 
178
    different from the previous value. The old value can still be
 
179
    retrieved using prevValue().
 
180
 
 
181
    \sa value()
 
182
*/
 
183
 
 
184
void Q3RangeControl::setValue(int value)
 
185
{
 
186
    directSetValue(value);
 
187
    if (prevVal != val)
 
188
        valueChange();
 
189
}
 
190
 
 
191
/*!
 
192
    Sets the range control \a value directly without calling
 
193
    valueChange().
 
194
 
 
195
    Forces the new \a value to be within the legal range.
 
196
 
 
197
    You will rarely have to call this function. However, if you want
 
198
    to change the range control's value inside the overloaded method
 
199
    valueChange(), setValue() would call the function valueChange()
 
200
    again. To avoid this recursion you must use directSetValue()
 
201
    instead.
 
202
 
 
203
    \sa setValue()
 
204
*/
 
205
 
 
206
void Q3RangeControl::directSetValue(int value)
 
207
{
 
208
    prevVal = val;
 
209
    val = bound(value);
 
210
}
 
211
 
 
212
/*!
 
213
    Equivalent to \c{setValue(value() + pageStep())}.
 
214
 
 
215
    If the value is changed, then valueChange() is called.
 
216
 
 
217
    \sa subtractPage() addLine() setValue()
 
218
*/
 
219
 
 
220
void Q3RangeControl::addPage()
 
221
{
 
222
    setValue(value() + pageStep());
 
223
}
 
224
 
 
225
/*!
 
226
    Equivalent to \c{setValue(value() - pageStep())}.
 
227
 
 
228
    If the value is changed, then valueChange() is called.
 
229
 
 
230
    \sa addPage() subtractLine() setValue()
 
231
*/
 
232
 
 
233
void Q3RangeControl::subtractPage()
 
234
{
 
235
    setValue(value() - pageStep());
 
236
}
 
237
 
 
238
/*!
 
239
    Equivalent to \c{setValue(value() + lineStep())}.
 
240
 
 
241
    If the value is changed, then valueChange() is called.
 
242
 
 
243
    \sa subtractLine() addPage() setValue()
 
244
*/
 
245
 
 
246
void Q3RangeControl::addLine()
 
247
{
 
248
    setValue(value() + lineStep());
 
249
}
 
250
 
 
251
/*!
 
252
    Equivalent to \c{setValue(value() - lineStep())}.
 
253
 
 
254
    If the value is changed, then valueChange() is called.
 
255
 
 
256
    \sa addLine() subtractPage() setValue()
 
257
*/
 
258
 
 
259
void Q3RangeControl::subtractLine()
 
260
{
 
261
    setValue(value() - lineStep());
 
262
}
 
263
 
 
264
 
 
265
/*!
 
266
    \fn int Q3RangeControl::minValue() const
 
267
 
 
268
    Returns the minimum value of the range.
 
269
 
 
270
    \sa setMinValue() setRange() maxValue()
 
271
*/
 
272
 
 
273
/*!
 
274
    \fn int Q3RangeControl::maxValue() const
 
275
 
 
276
    Returns the maximum value of the range.
 
277
 
 
278
    \sa setMaxValue() setRange() minValue()
 
279
*/
 
280
 
 
281
/*!
 
282
    Sets the minimum value of the range to \a minVal.
 
283
 
 
284
    If necessary, the maxValue() is adjusted so that the range remains
 
285
    valid.
 
286
 
 
287
    \sa minValue() setMaxValue()
 
288
*/
 
289
void Q3RangeControl::setMinValue(int minVal)
 
290
{
 
291
    int maxVal = maxValue();
 
292
    if (maxVal < minVal)
 
293
        maxVal = minVal;
 
294
    setRange(minVal, maxVal);
 
295
}
 
296
 
 
297
/*!
 
298
    Sets the minimum value of the range to \a maxVal.
 
299
 
 
300
    If necessary, the minValue() is adjusted so that the range remains
 
301
    valid.
 
302
 
 
303
    \sa maxValue() setMinValue()
 
304
*/
 
305
void Q3RangeControl::setMaxValue(int maxVal)
 
306
{
 
307
    int minVal = minValue();
 
308
    if (minVal > maxVal)
 
309
        minVal = maxVal;
 
310
    setRange(minVal, maxVal);
 
311
}
 
312
 
 
313
/*!
 
314
    Sets the range control's minimum value to \a minValue and its
 
315
    maximum value to \a maxValue.
 
316
 
 
317
    Calls the virtual rangeChange() function if one or both of the new
 
318
    minimum and maximum values are different from the previous
 
319
    setting. Calls the virtual valueChange() function if the current
 
320
    value is adjusted because it was outside the new range.
 
321
 
 
322
    If \a maxValue is smaller than \a minValue, \a minValue becomes
 
323
    the only legal value.
 
324
 
 
325
    \sa minValue() maxValue()
 
326
*/
 
327
 
 
328
void Q3RangeControl::setRange(int minValue, int maxValue)
 
329
{
 
330
    if (minValue > maxValue) {
 
331
        qWarning("Q3RangeControl::setRange: minValue %d > maxValue %d",
 
332
                  minValue, maxValue);
 
333
        maxValue = minValue;
 
334
    }
 
335
    if (minValue == minVal && maxValue == maxVal)
 
336
        return;
 
337
    minVal = minValue;
 
338
    maxVal = maxValue;
 
339
    int tmp = bound(val);
 
340
    rangeChange();
 
341
    if (tmp != val) {
 
342
        prevVal = val;
 
343
        val = tmp;
 
344
        valueChange();
 
345
    }
 
346
}
 
347
 
 
348
 
 
349
/*!
 
350
    \fn int Q3RangeControl::lineStep() const
 
351
 
 
352
    Returns the line step.
 
353
 
 
354
    \sa setSteps() pageStep()
 
355
*/
 
356
 
 
357
/*!
 
358
    \fn int Q3RangeControl::pageStep() const
 
359
 
 
360
    Returns the page step.
 
361
 
 
362
    \sa setSteps() lineStep()
 
363
*/
 
364
 
 
365
/*!
 
366
    Sets the range's line step to \a lineStep and page step to \a
 
367
    pageStep.
 
368
 
 
369
    Calls the virtual stepChange() function if the new line step
 
370
    or page step are different from the previous settings.
 
371
 
 
372
    \sa lineStep() pageStep() setRange()
 
373
*/
 
374
 
 
375
void Q3RangeControl::setSteps(int lineStep, int pageStep)
 
376
{
 
377
    if (lineStep != line || pageStep != page) {
 
378
        line = QABS(lineStep);
 
379
        page = QABS(pageStep);
 
380
        stepChange();
 
381
    }
 
382
}
 
383
 
 
384
 
 
385
/*!
 
386
    This virtual function is called whenever the range control value
 
387
    changes. You can reimplement it if you want to be notified when
 
388
    the value changes. The default implementation does nothing.
 
389
 
 
390
    Note that this method is called after the value has changed. The
 
391
    previous value can be retrieved using prevValue().
 
392
 
 
393
    \sa setValue(), addPage(), subtractPage(), addLine(),
 
394
    subtractLine() rangeChange(), stepChange()
 
395
*/
 
396
 
 
397
void Q3RangeControl::valueChange()
 
398
{
 
399
}
 
400
 
 
401
 
 
402
/*!
 
403
    This virtual function is called whenever the range control's range
 
404
    changes. You can reimplement it if you want to be notified when
 
405
    the range changes. The default implementation does nothing.
 
406
 
 
407
    Note that this method is called after the range has changed.
 
408
 
 
409
    \sa setRange(), valueChange(), stepChange()
 
410
*/
 
411
 
 
412
void Q3RangeControl::rangeChange()
 
413
{
 
414
}
 
415
 
 
416
 
 
417
/*!
 
418
    This virtual function is called whenever the range control's
 
419
    line or page step settings change. You can reimplement it if you
 
420
    want to be notified when the step changes. The default
 
421
    implementation does nothing.
 
422
 
 
423
    Note that this method is called after a step setting has changed.
 
424
 
 
425
    \sa setSteps(), rangeChange(), valueChange()
 
426
*/
 
427
 
 
428
void Q3RangeControl::stepChange()
 
429
{
 
430
}
 
431
 
 
432
 
 
433
/*!
 
434
    Forces the value \a v to be within the range from minValue() to
 
435
    maxValue() inclusive, and returns the result.
 
436
 
 
437
    This function is provided so that you can easily force other
 
438
    numbers than value() into the allowed range. You do not need to
 
439
    call it in order to use Q3RangeControl itself.
 
440
 
 
441
    \sa setValue() value() minValue() maxValue()
 
442
*/
 
443
 
 
444
int Q3RangeControl::bound(int v) const
 
445
{
 
446
    if (v < minVal)
 
447
        return minVal;
 
448
    if (v > maxVal)
 
449
        return maxVal;
 
450
    return v;
 
451
}
 
452
 
 
453
 
 
454
/*!
 
455
    Converts \a logical_val to a pixel position. minValue() maps to 0,
 
456
    maxValue() maps to \a span and other values are distributed evenly
 
457
    in-between.
 
458
 
 
459
    This function can handle the entire integer range without
 
460
    overflow, providing \a span is \<= 4096.
 
461
 
 
462
    Calling this method is useful when actually drawing a range
 
463
    control such as a QScrollBar on-screen.
 
464
 
 
465
    \sa valueFromPosition()
 
466
*/
 
467
 
 
468
int Q3RangeControl::positionFromValue(int logical_val, int span) const
 
469
{
 
470
    if (span <= 0 || logical_val < minValue() || maxValue() <= minValue())
 
471
        return 0;
 
472
    if (logical_val > maxValue())
 
473
        return span;
 
474
 
 
475
    uint range = maxValue() - minValue();
 
476
    uint p = logical_val - minValue();
 
477
 
 
478
    if (range > (uint)INT_MAX/4096) {
 
479
        const int scale = 4096*2;
 
480
        return ((p/scale) * span) / (range/scale);
 
481
        // ### the above line is probably not 100% correct
 
482
        // ### but fixing it isn't worth the extreme pain...
 
483
    } else if (range > (uint)span) {
 
484
        return (2*p*span + range) / (2*range);
 
485
    } else {
 
486
        uint div = span / range;
 
487
        uint mod = span % range;
 
488
        return p*div + (2*p*mod + range) / (2*range);
 
489
    }
 
490
    //equiv. to (p*span)/range + 0.5
 
491
    // no overflow because of this implicit assumption:
 
492
    // span <= 4096
 
493
}
 
494
 
 
495
 
 
496
/*!
 
497
    Converts the pixel position \a pos to a value. 0 maps to
 
498
    minValue(), \a span maps to maxValue() and other values are
 
499
    distributed evenly in-between.
 
500
 
 
501
    This function can handle the entire integer range without
 
502
    overflow.
 
503
 
 
504
    Calling this method is useful if you actually implemented a range
 
505
    control widget such as QScrollBar and want to handle mouse press
 
506
    events. This function then maps screen coordinates to the logical
 
507
    values.
 
508
 
 
509
    \sa positionFromValue()
 
510
*/
 
511
 
 
512
int Q3RangeControl::valueFromPosition(int pos, int span) const
 
513
{
 
514
    if (span <= 0 || pos <= 0)
 
515
        return minValue();
 
516
    if (pos >= span)
 
517
        return maxValue();
 
518
 
 
519
    uint range = maxValue() - minValue();
 
520
 
 
521
    if ((uint)span > range)
 
522
        return  minValue() + (2*pos*range + span) / (2*span);
 
523
    else {
 
524
        uint div = range / span;
 
525
        uint mod = range % span;
 
526
        return  minValue() + pos*div + (2*pos*mod + span) / (2*span);
 
527
    }
 
528
    // equiv. to minValue() + (pos*range)/span + 0.5
 
529
    // no overflow because of this implicit assumption:
 
530
    // pos <= span < sqrt(INT_MAX+0.0625)+0.25 ~ sqrt(INT_MAX)
 
531
}
 
532
#endif