source: trunk/src/qt3support/widgets/q3spinwidget.cpp@ 345

Last change on this file since 345 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 10.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the Qt3Support module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
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**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "q3rangecontrol.h"
43
44#ifndef QT_NO_SPINWIDGET
45
46#include "qabstractspinbox.h"
47#include "qevent.h"
48#include "qpainter.h"
49#include "qrect.h"
50#include "qstyle.h"
51#include "qstyleoption.h"
52#include "qtimer.h"
53
54QT_BEGIN_NAMESPACE
55
56class Q3SpinWidgetPrivate
57{
58public:
59 Q3SpinWidgetPrivate()
60 : upEnabled(true),
61 downEnabled(true),
62 theButton(0),
63 buttonDown(0),
64 timerUp(0),
65 bsyms(Q3SpinWidget::UpDownArrows),
66 ed (0) {}
67 uint upEnabled :1;
68 uint downEnabled :1;
69 uint theButton :2;
70 uint buttonDown :2;
71 uint timerUp : 1;
72 QRect up;
73 QRect down;
74 QTimer auRepTimer;
75 Q3SpinWidget::ButtonSymbols bsyms;
76 QWidget *ed;
77 void startTimer(int msec) { auRepTimer.start(msec, true); }
78 void startTimer(bool up, int msec) { timerUp = up; startTimer(msec); }
79 void stopTimer() { auRepTimer.stop(); }
80};
81
82/*!
83 \class Q3SpinWidget
84 \brief The Q3SpinWidget class is an internal range control related class.
85
86 \internal
87
88 Constructs an empty range control widget with parent \a parent
89 called \a name.
90
91*/
92
93Q3SpinWidget::Q3SpinWidget(QWidget* parent, const char* name)
94 : QWidget(parent, name)
95{
96 d = new Q3SpinWidgetPrivate();
97 connect(&d->auRepTimer, SIGNAL(timeout()), this, SLOT(timerDone()));
98 setFocusPolicy(Qt::StrongFocus);
99
100 arrange();
101 updateDisplay();
102}
103
104
105/*! Destroys the object and frees any allocated resources.
106
107*/
108
109Q3SpinWidget::~Q3SpinWidget()
110{
111 delete d;
112}
113
114/*! */
115QWidget * Q3SpinWidget::editWidget()
116{
117 return d->ed;
118}
119
120/*!
121 Sets the editing widget to \a w.
122*/
123void Q3SpinWidget::setEditWidget(QWidget * w)
124{
125 if (w) {
126 if (w->parentWidget() != this)
127 w->setParent(this);
128 setFocusProxy(w);
129 }
130 d->ed = w;
131 arrange();
132 updateDisplay();
133}
134
135/*! \reimp
136
137*/
138
139void Q3SpinWidget::mousePressEvent(QMouseEvent *e)
140{
141 if (e->button() != Qt::LeftButton) {
142 d->stopTimer();
143 d->buttonDown = 0;
144 d->theButton = 0;
145 repaint(d->down.united(d->up));
146 return;
147 }
148
149 uint oldButtonDown = d->buttonDown;
150
151 if (d->down.contains(e->pos()) && d->downEnabled)
152 d->buttonDown = 1;
153 else if (d->up.contains(e->pos()) && d->upEnabled)
154 d->buttonDown = 2;
155 else
156 d->buttonDown = 0;
157
158 d->theButton = d->buttonDown;
159 if (oldButtonDown != d->buttonDown) {
160 if (!d->buttonDown) {
161 repaint(d->down.united(d->up));
162 } else if (d->buttonDown & 1) {
163 repaint(d->down);
164 stepDown();
165 d->startTimer(false, 300);
166 } else if (d->buttonDown & 2) {
167 repaint(d->up);
168 stepUp();
169 d->startTimer(true, 300);
170 }
171 }
172
173 if (!oldButtonDown && !d->buttonDown)
174 e->ignore();
175
176}
177
178static QStyleOptionSpinBox getStyleOption(const Q3SpinWidget *spin)
179{
180 QStyleOptionSpinBox opt;
181 opt.init(spin);
182 opt.frame = true;
183 opt.subControls = 0;
184 opt.buttonSymbols = (QAbstractSpinBox::ButtonSymbols)spin->buttonSymbols();
185 opt.stepEnabled = 0;
186 if (spin->isUpEnabled())
187 opt.stepEnabled |= QAbstractSpinBox::StepUpEnabled;
188 if (spin->isDownEnabled())
189 opt.stepEnabled |= QAbstractSpinBox::StepDownEnabled;
190 opt.activeSubControls = 0;
191 return opt;
192}
193
194/*!
195
196*/
197
198void Q3SpinWidget::arrange()
199{
200 QStyleOptionSpinBox opt = getStyleOption(this);
201 d->up = style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxUp, this);
202 d->down = style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxDown, this);
203 if (d->ed) {
204 QRect r = style()->subControlRect(QStyle::CC_SpinBox, &opt,
205 QStyle::SC_SpinBoxEditField, this);
206 d->ed->setGeometry(r);
207 }
208}
209
210/*!
211
212*/
213
214void Q3SpinWidget::stepUp()
215{
216 emit stepUpPressed();
217}
218
219void Q3SpinWidget::resizeEvent(QResizeEvent*)
220{
221 arrange();
222}
223
224/*!
225
226*/
227
228void Q3SpinWidget::stepDown()
229{
230 emit stepDownPressed();
231}
232
233
234void Q3SpinWidget::timerDone()
235{
236 // we use a double timer to make it possible for users to do
237 // something with 0-timer on valueChanged.
238 QTimer::singleShot(1, this, SLOT(timerDoneEx()));
239}
240
241void Q3SpinWidget::timerDoneEx()
242{
243 if (!d->buttonDown)
244 return;
245 if (d->timerUp)
246 stepUp();
247 else
248 stepDown();
249 d->startTimer(100);
250}
251
252
253/*!
254 The event is passed in \a e.
255*/
256
257void Q3SpinWidget::mouseReleaseEvent(QMouseEvent *e)
258{
259 if (e->button() != Qt::LeftButton)
260 return;
261
262 uint oldButtonDown = d->theButton;
263 d->theButton = 0;
264 if (oldButtonDown != d->theButton) {
265 if (oldButtonDown & 1)
266 repaint(d->down);
267 else if (oldButtonDown & 2)
268 repaint(d->up);
269 }
270 d->stopTimer();
271 d->buttonDown = 0;
272
273 if (!oldButtonDown && !d->buttonDown)
274 e->ignore();
275}
276
277
278/*!
279 The event is passed in \a e.
280*/
281
282void Q3SpinWidget::mouseMoveEvent(QMouseEvent *e)
283{
284 if (!(e->state() & Qt::LeftButton))
285 return;
286
287 uint oldButtonDown = d->theButton;
288 if (oldButtonDown & 1 && !d->down.contains(e->pos())) {
289 d->stopTimer();
290 d->theButton = 0;
291 repaint(d->down);
292 } else if (oldButtonDown & 2 && !d->up.contains(e->pos())) {
293 d->stopTimer();
294 d->theButton = 0;
295 repaint(d->up);
296 } else if (!oldButtonDown && d->up.contains(e->pos()) && d->buttonDown & 2) {
297 d->startTimer(500);
298 d->theButton = 2;
299 repaint(d->up);
300 } else if (!oldButtonDown && d->down.contains(e->pos()) && d->buttonDown & 1) {
301 d->startTimer(500);
302 d->theButton = 1;
303 repaint(d->down);
304 }
305
306 if (!oldButtonDown && !d->buttonDown)
307 e->ignore();
308}
309
310
311/*!
312 The event is passed in \a e.
313*/
314#ifndef QT_NO_WHEELEVENT
315void Q3SpinWidget::wheelEvent(QWheelEvent *e)
316{
317 e->accept();
318 static float offset = 0;
319 static Q3SpinWidget* offset_owner = 0;
320 if (offset_owner != this) {
321 offset_owner = this;
322 offset = 0;
323 }
324 offset += -e->delta()/120;
325 if (QABS(offset) < 1)
326 return;
327 int ioff = int(offset);
328 int i;
329 for(i=0; i < QABS(ioff); i++)
330 offset > 0 ? stepDown() : stepUp();
331 offset -= ioff;
332}
333#endif
334
335/*!
336
337*/
338void Q3SpinWidget::paintEvent(QPaintEvent *)
339{
340 QPainter p(this);
341 QStyleOptionSpinBox opt = getStyleOption(this);
342
343 if (d->theButton & 1)
344 opt.activeSubControls = QStyle::SC_SpinBoxDown;
345 else if (d->theButton & 2)
346 opt.activeSubControls = QStyle::SC_SpinBoxUp;
347 else
348 opt.activeSubControls = QStyle::SC_None;
349 opt.rect = style()->subControlRect(QStyle::CC_SpinBox, &opt, QStyle::SC_SpinBoxFrame, this);
350 opt.subControls = QStyle::SC_All;
351 style()->drawComplexControl(QStyle::CC_SpinBox, &opt, &p, this);
352}
353
354
355// ### What does the QEvent passed in contain? It used to be the previous style.
356/*!
357 The previous style is passed in \a ev.
358*/
359void Q3SpinWidget::changeEvent(QEvent *ev)
360{
361 if(ev->type() == QEvent::StyleChange) {
362 arrange();
363 } else if(ev->type() == QEvent::ActivationChange) {
364 if (!isActiveWindow() && d->buttonDown) { //was active, but lost focus
365 d->stopTimer();
366 d->buttonDown = 0;
367 d->theButton = 0;
368 }
369 } else if(ev->type() == QEvent::EnabledChange) {
370 d->upEnabled = isEnabled();
371 d->downEnabled = isEnabled();
372 updateDisplay();
373 }
374 QWidget::changeEvent(ev);
375}
376
377/*!
378*/
379
380QRect Q3SpinWidget::upRect() const
381{
382 return d->up;
383}
384
385/*!
386*/
387
388QRect Q3SpinWidget::downRect() const
389{
390 return d->down;
391}
392
393/*!
394*/
395
396void Q3SpinWidget::updateDisplay()
397{
398 if (!isEnabled()) {
399 d->upEnabled = false;
400 d->downEnabled = false;
401 }
402 if (d->theButton & 1 && (d->downEnabled) == 0) {
403 d->theButton &= ~1;
404 d->buttonDown &= ~1;
405 }
406
407 if (d->theButton & 2 && (d->upEnabled) == 0) {
408 d->theButton &= ~2;
409 d->buttonDown &= ~2;
410 }
411 repaint();
412}
413
414/*!
415 Sets up-enabled to \a on.
416*/
417
418void Q3SpinWidget::setUpEnabled(bool on)
419{
420 if ((bool)d->upEnabled != on) {
421 d->upEnabled = on;
422 updateDisplay();
423 }
424}
425
426/*!
427*/
428
429bool Q3SpinWidget::isUpEnabled() const
430{
431 return d->upEnabled;
432}
433
434/*!
435 Sets down-enabled to \a on.
436*/
437
438void Q3SpinWidget::setDownEnabled(bool on)
439{
440 if ((bool)d->downEnabled != on) {
441 d->downEnabled = on;
442 updateDisplay();
443 }
444}
445
446/*!
447*/
448
449bool Q3SpinWidget::isDownEnabled() const
450{
451 return d->downEnabled;
452}
453
454/*!
455 Sets the button symbol to \a bs.
456*/
457
458void Q3SpinWidget::setButtonSymbols(ButtonSymbols bs)
459{
460 d->bsyms = bs;
461}
462
463/*!
464*/
465
466Q3SpinWidget::ButtonSymbols Q3SpinWidget::buttonSymbols() const
467{
468 return d->bsyms;
469}
470
471QT_END_NAMESPACE
472
473#endif
Note: See TracBrowser for help on using the repository browser.