source: trunk/src/gui/widgets/qdial.cpp@ 1166

Last change on this file since 1166 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 14.0 KB
RevLine 
[2]1/****************************************************************************
2**
[846]3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
[561]4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
[2]6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
[561]24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
[2]27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
[561]36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
[2]38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdial.h"
43
44#ifndef QT_NO_DIAL
45
46#include <qapplication.h>
47#include <qbitmap.h>
48#include <qcolor.h>
49#include <qevent.h>
50#include <qpainter.h>
51#include <qpolygon.h>
52#include <qregion.h>
53#include <qstyle.h>
54#include <qstylepainter.h>
55#include <qstyleoption.h>
56#include <qslider.h>
57#include <private/qabstractslider_p.h>
58#include <private/qmath_p.h>
59#ifndef QT_NO_ACCESSIBILITY
60#include "qaccessible.h"
61#endif
[561]62#include <qmath.h>
[2]63
64QT_BEGIN_NAMESPACE
65
66class QDialPrivate : public QAbstractSliderPrivate
67{
68 Q_DECLARE_PUBLIC(QDial)
69public:
70 QDialPrivate()
71 {
72 wrapping = false;
73 tracking = true;
74 doNotEmit = false;
75 target = qreal(3.7);
76 }
77
78 qreal target;
79 uint showNotches : 1;
80 uint wrapping : 1;
81 uint doNotEmit : 1;
82
83 int valueFromPoint(const QPoint &) const;
84 double angle(const QPoint &, const QPoint &) const;
85 void init();
86};
87
88void QDialPrivate::init()
89{
90 Q_Q(QDial);
91 showNotches = false;
92 q->setFocusPolicy(Qt::WheelFocus);
93#ifdef QT3_SUPPORT
94 QObject::connect(q, SIGNAL(sliderPressed()), q, SIGNAL(dialPressed()));
95 QObject::connect(q, SIGNAL(sliderMoved(int)), q, SIGNAL(dialMoved(int)));
96 QObject::connect(q, SIGNAL(sliderReleased()), q, SIGNAL(dialReleased()));
97#endif
98}
99
100/*!
101 Initialize \a option with the values from this QDial. This method
102 is useful for subclasses when they need a QStyleOptionSlider, but don't want
103 to fill in all the information themselves.
104
105 \sa QStyleOption::initFrom()
106*/
107void QDial::initStyleOption(QStyleOptionSlider *option) const
108{
109 if (!option)
110 return;
111
112 Q_D(const QDial);
113 option->initFrom(this);
114 option->minimum = d->minimum;
115 option->maximum = d->maximum;
116 option->sliderPosition = d->position;
117 option->sliderValue = d->value;
118 option->singleStep = d->singleStep;
119 option->pageStep = d->pageStep;
120 option->upsideDown = !d->invertedAppearance;
121 option->notchTarget = d->target;
122 option->dialWrapping = d->wrapping;
123 option->subControls = QStyle::SC_All;
124 option->activeSubControls = QStyle::SC_None;
125 if (!d->showNotches) {
126 option->subControls &= ~QStyle::SC_DialTickmarks;
127 option->tickPosition = QSlider::TicksAbove;
128 } else {
129 option->tickPosition = QSlider::NoTicks;
130 }
131 option->tickInterval = notchSize();
132}
133
134int QDialPrivate::valueFromPoint(const QPoint &p) const
135{
136 Q_Q(const QDial);
137 double yy = (double)q->height()/2.0 - p.y();
138 double xx = (double)p.x() - q->width()/2.0;
[561]139 double a = (xx || yy) ? qAtan2(yy, xx) : 0;
[2]140
141 if (a < Q_PI / -2)
142 a = a + Q_PI * 2;
143
144 int dist = 0;
145 int minv = minimum, maxv = maximum;
146
147 if (minimum < 0) {
148 dist = -minimum;
149 minv = 0;
150 maxv = maximum + dist;
151 }
152
153 int r = maxv - minv;
154 int v;
155 if (wrapping)
156 v = (int)(0.5 + minv + r * (Q_PI * 3 / 2 - a) / (2 * Q_PI));
157 else
158 v = (int)(0.5 + minv + r* (Q_PI * 4 / 3 - a) / (Q_PI * 10 / 6));
159
160 if (dist > 0)
161 v -= dist;
162
163 return !invertedAppearance ? bound(v) : maximum - bound(v);
164}
165
166/*!
167 \class QDial
168
169 \brief The QDial class provides a rounded range control (like a speedometer or potentiometer).
170
171 \ingroup basicwidgets
172
[561]173
[2]174 QDial is used when the user needs to control a value within a
175 program-definable range, and the range either wraps around
176 (for example, with angles measured from 0 to 359 degrees) or the
177 dialog layout needs a square widget.
178
179 Since QDial inherits from QAbstractSlider, the dial behaves in
180 a similar way to a \l{QSlider}{slider}. When wrapping() is false
181 (the default setting) there is no real difference between a slider
182 and a dial. They both share the same signals, slots and member
183 functions. Which one you use depends on the expectations of
184 your users and on the type of application.
185
186 The dial initially emits valueChanged() signals continuously while
187 the slider is being moved; you can make it emit the signal less
188 often by disabling the \l{QAbstractSlider::tracking} {tracking}
189 property. The sliderMoved() signal is emitted continuously even
190 when tracking is disabled.
191
192 The dial also emits sliderPressed() and sliderReleased() signals
193 when the mouse button is pressed and released. Note that the
194 dial's value can change without these signals being emitted since
195 the keyboard and wheel can also be used to change the value.
196
197 Unlike the slider, QDial attempts to draw a "nice" number of
198 notches rather than one per line step. If possible, the number of
199 notches drawn is one per line step, but if there aren't enough pixels
200 to draw every one, QDial will skip notches to try and draw a uniform
201 set (e.g. by drawing every second or third notch).
202
203 Like the slider, the dial makes the QAbstractSlider functions
204 setValue(), addLine(), subtractLine(), addPage() and
205 subtractPage() available as slots.
206
207 The dial's keyboard interface is fairly simple: The
208 \key{left}/\key{up} and \key{right}/\key{down} arrow keys adjust
209 the dial's \l {QAbstractSlider::value} {value} by the defined
210 \l {QAbstractSlider::singleStep} {singleStep}, \key{Page Up} and
211 \key{Page Down} by the defined \l {QAbstractSlider::pageStep}
212 {pageStep}, and the \key Home and \key End keys set the value to
213 the defined \l {QAbstractSlider::minimum} {minimum} and
214 \l {QAbstractSlider::maximum} {maximum} values.
215
216 If you are using the mouse wheel to adjust the dial, the increment
217 value is determined by the lesser value of
218 \l{QApplication::wheelScrollLines()} {wheelScrollLines} multipled
219 by \l {QAbstractSlider::singleStep} {singleStep}, and
220 \l {QAbstractSlider::pageStep} {pageStep}.
221
222 \table
223 \row \o \inlineimage plastique-dial.png Screenshot of a dial in the Plastique widget style
224 \o \inlineimage windowsxp-dial.png Screenshot of a dial in the Windows XP widget style
225 \o \inlineimage macintosh-dial.png Screenshot of a dial in the Macintosh widget style
226 \row \o {3,1} Dials shown in various widget styles (from left to right):
227 \l{Plastique Style Widget Gallery}{Plastique},
228 \l{Windows XP Style Widget Gallery}{Windows XP},
229 \l{Macintosh Style Widget Gallery}{Macintosh}.
230 \endtable
231
232 \sa QScrollBar, QSpinBox, QSlider, {fowler}{GUI Design Handbook: Slider}, {Sliders Example}
233*/
234
235/*!
236 Constructs a dial.
237
238 The \a parent argument is sent to the QAbstractSlider constructor.
239*/
240QDial::QDial(QWidget *parent)
241 : QAbstractSlider(*new QDialPrivate, parent)
242{
243 Q_D(QDial);
244 d->init();
245}
246
247#ifdef QT3_SUPPORT
248/*!
249 Use one of the constructors that doesn't take the \a name
250 argument and then use setObjectName() instead.
251*/
252QDial::QDial(QWidget *parent, const char *name)
253 : QAbstractSlider(*new QDialPrivate, parent)
254{
255 Q_D(QDial);
256 setObjectName(QString::fromAscii(name));
257 d->init();
258}
259
260/*!
261 Use one of the constructors that doesn't take the \a name
262 argument and then use setObjectName() instead.
263*/
264QDial::QDial(int minValue, int maxValue, int pageStep, int value,
265 QWidget *parent, const char *name)
266 : QAbstractSlider(*new QDialPrivate, parent)
267{
268 Q_D(QDial);
269 setObjectName(QString::fromAscii(name));
270 d->minimum = minValue;
271 d->maximum = maxValue;
272 d->pageStep = pageStep;
273 d->position = d->value = value;
274 d->init();
275}
276#endif
277/*!
278 Destroys the dial.
279*/
280QDial::~QDial()
281{
282}
283
284/*! \reimp */
285void QDial::resizeEvent(QResizeEvent *e)
286{
287 QWidget::resizeEvent(e);
288}
289