1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the widgets module of the Qt Toolkit.
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.
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.
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.
21
** Contact info@trolltech.com if any conditions of this licensing are
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.
27
****************************************************************************/
33
#include <qapplication.h>
41
#include <qstylepainter.h>
42
#include <qstyleoption.h>
44
#include <private/qabstractslider_p.h>
45
#include <private/qmath_p.h>
46
#ifndef QT_NO_ACCESSIBILITY
47
#include "qaccessible.h"
50
class QDialPrivate : public QAbstractSliderPrivate
52
Q_DECLARE_PUBLIC(QDial)
67
int valueFromPoint(const QPoint &) const;
68
double angle(const QPoint &, const QPoint &) const;
70
QStyleOptionSlider getStyleOption() const;
73
void QDialPrivate::init()
77
q->setFocusPolicy(Qt::WheelFocus);
79
QObject::connect(q, SIGNAL(sliderPressed()), q, SIGNAL(dialPressed()));
80
QObject::connect(q, SIGNAL(sliderMoved(int)), q, SIGNAL(dialMoved(int)));
81
QObject::connect(q, SIGNAL(sliderReleased()), q, SIGNAL(dialReleased()));
85
QStyleOptionSlider QDialPrivate::getStyleOption() const
88
QStyleOptionSlider opt;
90
opt.minimum = minimum;
91
opt.maximum = maximum;
92
opt.sliderPosition = position;
93
opt.sliderValue = value;
94
opt.singleStep = singleStep;
95
opt.pageStep = pageStep;
96
opt.upsideDown = !invertedAppearance;
97
opt.notchTarget = target;
98
opt.dialWrapping = wrapping;
99
opt.subControls = QStyle::SC_All;
100
opt.activeSubControls = QStyle::SC_None;
102
opt.subControls &= ~QStyle::SC_DialTickmarks;
103
opt.tickPosition = QSlider::TicksAbove;
104
opt.tickInterval = q->notchSize();
106
opt.tickPosition = QSlider::NoTicks;
107
opt.tickInterval = 0;
112
int QDialPrivate::valueFromPoint(const QPoint &p) const
115
double yy = (double)q->height()/2.0 - p.y();
116
double xx = (double)p.x() - q->width()/2.0;
117
double a = (xx || yy) ? atan2(yy, xx) : 0;
123
int minv = minimum, maxv = maximum;
128
maxv = maximum + dist;
134
v = (int)(0.5 + minv + r * (Q_PI * 3 / 2 - a) / (2 * Q_PI));
136
v = (int)(0.5 + minv + r* (Q_PI * 4 / 3 - a) / (Q_PI * 10 / 6));
147
\brief The QDial class provides a rounded range control (like a speedometer or potentiometer).
152
QDial is used when the user needs to control a value within a
153
program-definable range, and the range either wraps around
154
(typically, 0..359 degrees) or the dialog layout needs a square
157
Both API- and UI-wise, the dial is very similar to a \link QSlider
158
slider. \endlink Indeed, when wrapping() is false (the default)
159
there is no real difference between a slider and a dial. They
160
have the same signals, slots and member functions, all of which do
161
the same things. Which one you use depends only on your taste
162
and on the application.
164
The dial initially emits valueChanged() signals continuously while
165
the slider is being moved; you can make it emit the signal less
166
often by calling setTracking(false). dialMoved() is emitted
167
continuously even when tracking() is false.
169
The slider also emits dialPressed() and dialReleased() signals
170
when the mouse button is pressed and released. But note that the
171
dial's value can change without these signals being emitted; the
172
keyboard and wheel can be used to change the value.
174
Unlike the slider, QDial attempts to draw a "nice" number of
175
notches rather than one per lineStep(). If possible, the number
176
of notches drawn is one per lineStep(), but if there aren't enough
177
pixels to draw every one, QDial will draw every second, third
178
etc., notch. notchSize() returns the number of units per notch,
179
hopefully a multiple of lineStep(); setNotchTarget() sets the
180
target distance between neighbouring notches in pixels. The
181
default is 3.75 pixels.
183
Like the slider, the dial makes the QAbstractSlider functions
184
setValue(), addLine(), subtractLine(), addPage() and
185
subtractPage() available as slots.
187
The dial's keyboard interface is fairly simple: The left/up and
188
right/down arrow keys move by lineStep(), page up and page down by
189
pageStep() and Home and End to minValue() and maxValue().
191
\inlineimage qdial-m.png Screenshot in Motif style
192
\inlineimage qdial-w.png Screenshot in Windows style
194
\sa QScrollBar, QSpinBox, {fowler}{GUI Design Handbook: Slider}
200
The \a parent argument is sent to the QAbstractSlider constructor.
202
QDial::QDial(QWidget *parent)
203
: QAbstractSlider(*new QDialPrivate, parent)
211
Use one of the constructors that doesn't take the \a name
212
argument and then use setObjectName() instead.
214
QDial::QDial(QWidget *parent, const char *name)
215
: QAbstractSlider(*new QDialPrivate, parent)
223
Use one of the constructors that doesn't take the \a name
224
argument and then use setObjectName() instead.
226
QDial::QDial(int minValue, int maxValue, int pageStep, int value,
227
QWidget *parent, const char *name)
228
: QAbstractSlider(*new QDialPrivate, parent)
232
d->minimum = minValue;
233
d->maximum = maxValue;
234
d->pageStep = pageStep;
235
d->position = d->value = value;
247
void QDial::resizeEvent(QResizeEvent *e)
249
QWidget::resizeEvent(e);
256
void QDial::paintEvent(QPaintEvent *)
259
QStylePainter p(this);
260
p.drawComplexControl(QStyle::CC_Dial, d->getStyleOption());
267
void QDial::mousePressEvent(QMouseEvent *e)
270
if (d->maximum == d->minimum ||
271
(e->button() != Qt::LeftButton) ||
272
(e->buttons() ^ e->button())) {
277
setSliderPosition(d->valueFromPoint(e->pos()));
278
emit sliderPressed();
286
void QDial::mouseReleaseEvent(QMouseEvent * e)
289
if (e->buttons() ^ e->button()) {
294
setValue(d->valueFromPoint(e->pos()));
295
emit sliderReleased();
303
void QDial::mouseMoveEvent(QMouseEvent * e)
306
if (!d->tracking || !(e->buttons() & Qt::LeftButton)) {
312
setSliderPosition(d->valueFromPoint(e->pos()));
313
emit sliderMoved(d->value);
314
d->doNotEmit = false;
321
Reimplemented to ensure the display is correct and to emit the
322
valueChanged(int) signal when appropriate and to ensure
323
tickmarks are consistent with the new range. The \a change
324
parameter indicates what type of change that has taken place.
327
void QDial::sliderChange(SliderChange change)
330
if (change == SliderRangeChange || change == SliderValueChange) {
332
if (change == SliderValueChange && (d->tracking || !d->doNotEmit)) {
333
emit valueChanged(d->value);
334
#ifndef QT_NO_ACCESSIBILITY
335
QAccessible::updateAccessibility(this, 0, QAccessible::ValueChanged);
341
void QDial::setWrapping(bool enable)
344
if (d->wrapping == enable)
346
d->wrapping = enable;
352
\property QDial::wrapping
353
\brief whether wrapping is enabled
355
If true, wrapping is enabled. This means that the arrow can be
356
turned around 360�. Otherwise there is some space at the bottom of
357
the dial which is skipped by the arrow.
359
This property's default is false.
362
bool QDial::wrapping() const
370
\property QDial::notchSize
371
\brief the current notch size
373
The notch size is in range control units, not pixels, and if
374
possible it is a multiple of lineStep() that results in an
375
on-screen notch size near notchTarget().
377
\sa notchTarget() lineStep()
380
int QDial::notchSize() const
384
int r = qMin(width(), height())/2;
385
// length of the whole arc
386
int l = (int)(r * (d->wrapping ? 6 : 5) * Q_PI / 6);
387
// length of the arc from minValue() to minValue()+pageStep()
388
if (d->maximum > d->minimum + d->pageStep)
389
l = (int)(0.5 + l * d->pageStep / (d->maximum - d->minimum));
390
// length of a singleStep arc
391
l = l * d->singleStep / d->pageStep;
394
// how many times singleStep can be draw in d->target pixels
395
l = (int)(0.5 + d->target / l);
396
// we want notchSize() to be a non-zero multiple of lineStep()
399
return d->singleStep * l;
402
void QDial::setNotchTarget(double target)
410
\property QDial::notchTarget
411
\brief the target number of pixels between notches
413
The notch target is the number of pixels QDial attempts to put
416
The actual size may differ from the target size.
418
qreal QDial::notchTarget() const
425
void QDial::setNotchesVisible(bool visible)
427
// d->showNotches = visible;
429
// ### fix after beta2
434
\property QDial::notchesVisible
435
\brief whether the notches are shown
437
If true, the notches are shown. If false (the default) notches are
440
bool QDial::notchesVisible() const
443
return d->showNotches;
450
QSize QDial::minimumSizeHint() const
452
return QSize(50, 50);
459
QSize QDial::sizeHint() const
461
return QSize(100, 100).expandedTo(QApplication::globalStrut());
465
\fn void QDial::dialPressed();
467
Use QAbstractSlider::sliderPressed() instead.
471
\fn void QDial::dialMoved(int value);
473
Use QAbstractSlider::sliderMoved() instead.
477
\fn void QDial::dialReleased();
479
Use QAbstractSlider::sliderReleased() instead.
483
#endif // QT_FEATURE_DIAL