# qwt_counter.cpp

    00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
    00002  * Qwt Widget Library
    00003  * Copyright (C) 1997   Josef Wilgen
    00004  * Copyright (C) 2002   Uwe Rathmann
    00005  *
    00006  * This library is free software; you can redistribute it and/or
    00007  * modify it under the terms of the Qwt License, Version 1.0
    00008  *****************************************************************************/
    00009
    00010 // vim: expandtab
    00011
    00012 #include <qlayout.h>
    00013 #include <qlineedit.h>
    00014 #include <qvalidator.h>
    00015 #include <qevent.h>
    00016 #include <qstyle.h>
    00017 #include "qwt_math.h"
    00018 #include "qwt_counter.h"
    00019 #include "qwt_arrow_button.h"
    00020
    00021 class QwtCounter::PrivateData
    00022 {
    00023 public:
    00024     PrivateData():
    00025         editable(true)
    00026     {
    00027         increment[Button1] = 1;
    00028         increment[Button2] = 10;
    00029         increment[Button3] = 100;
    00030     }
    00031
    00032     QwtArrowButton *buttonDown[ButtonCnt];
    00033     QwtArrowButton *buttonUp[ButtonCnt];
    00034     QLineEdit *valueEdit;
    00035
    00036     int increment[ButtonCnt];
    00037     int nButtons;
    00038
    00039     bool editable;
    00040 };
    00041
    00050 QwtCounter::QwtCounter(QWidget *parent):
    00051     QWidget(parent)
    00052 {
    00053     initCounter();
    00054 }
    00055
    00056 #if QT_VERSION < 0x040000
    00057
    00065 QwtCounter::QwtCounter(QWidget *parent, const char *name):
    00066     QWidget(parent, name)
    00067 {
    00068     initCounter();
    00069 }
    00070 #endif
    00071
    00072 void QwtCounter::initCounter()
    00073 {
    00074     d_data = new PrivateData;
    00075
    00076 #if QT_VERSION >= 0x040000
    00077     using namespace Qt;
    00078 #endif
    00079
    00080     QHBoxLayout *layout = new QHBoxLayout(this);
    00081     layout->setSpacing(0);
    00082     layout->setMargin(0);
    00083
    00084     int i;
    00085     for(i = ButtonCnt - 1; i >= 0; i--)
    00086     {
    00087         QwtArrowButton *btn =
    00088             new QwtArrowButton(i+1, Qt::DownArrow,this);
    00089         btn->setFocusPolicy(NoFocus);
    00090         btn->installEventFilter(this);
    00091         layout->addWidget(btn);
    00092
    00093         connect(btn, SIGNAL(released()), SLOT(btnReleased()));
    00094         connect(btn, SIGNAL(clicked()), SLOT(btnClicked()));
    00095
    00096         d_data->buttonDown[i] = btn;
    00097     }
    00098
    00099     d_data->valueEdit = new QLineEdit(this);
    00100     d_data->valueEdit->setReadOnly(false);
    00101     d_data->valueEdit->setValidator(new QDoubleValidator(d_data->valueEdit));
    00102     layout->addWidget(d_data->valueEdit);
    00103
    00104 #if QT_VERSION >= 0x040000
    00105     connect( d_data->valueEdit, SIGNAL(editingFinished()),
    00106         SLOT(textChanged()) );
    00107 #else
    00108     connect( d_data->valueEdit, SIGNAL(returnPressed()), SLOT(textChanged()) );
    00109     connect( d_data->valueEdit, SIGNAL(lostFocus()), SLOT(textChanged()) );
    00110 #endif
    00111
    00112     layout->setStretchFactor(d_data->valueEdit, 10);
    00113
    00114     for(i = 0; i < ButtonCnt; i++)
    00115     {
    00116 #if QT_VERSION >= 0x040000
    00117         using namespace Qt;
    00118 #endif
    00119         QwtArrowButton *btn =
    00120             new QwtArrowButton(i+1, Qt::UpArrow, this);
    00121         btn->setFocusPolicy(NoFocus);
    00122         btn->installEventFilter(this);
    00123         layout->addWidget(btn);
    00124
    00125         connect(btn, SIGNAL(released()), SLOT(btnReleased()));
    00126         connect(btn, SIGNAL(clicked()), SLOT(btnClicked()));
    00127
    00128         d_data->buttonUp[i] = btn;
    00129     }
    00130
    00131     setNumButtons(2);
    00132     setRange(0.0,1.0,0.001);
    00133     setValue(0.0);
    00134
    00135     setSizePolicy(
    00136         QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
    00137
    00138     setFocusProxy(d_data->valueEdit);
    00139     setFocusPolicy(StrongFocus);
    00140 }
    00141
    00143 QwtCounter::~QwtCounter()
    00144 {
    00145     delete d_data;
    00146 }
    00147
    00151 void QwtCounter::polish()
    00152 {
    00153     const int w = d_data->valueEdit->fontMetrics().width("W") + 8;
    00154
    00155     for ( int i = 0; i < ButtonCnt; i++ )
    00156     {
    00157         d_data->buttonDown[i]->setMinimumWidth(w);
    00158         d_data->buttonUp[i]->setMinimumWidth(w);
    00159     }
    00160
    00161 #if QT_VERSION < 0x040000
    00162     QWidget::polish();
    00163 #endif
    00164 }
    00165
    00167 void QwtCounter::textChanged()
    00168 {
    00169     if ( !d_data->editable )
    00170         return;
    00171
    00172     bool converted = false;
    00173
    00174     const double value = d_data->valueEdit->text().toDouble(&converted);
    00175     if ( converted )
    00176        setValue( value );
    00177 }
    00178
    00185 void QwtCounter::setEditable(bool editable)
    00186 {
    00187 #if QT_VERSION >= 0x040000
    00188     using namespace Qt;
    00189 #endif
    00190     if ( editable == d_data->editable )
    00191         return;
    00192
    00193     d_data->editable = editable;
    00194     d_data->valueEdit->setReadOnly(!editable);
    00195 }
    00196
    00198 bool QwtCounter::editable() const
    00199 {
    00200     return d_data->editable;
    00201 }
    00202
    00206 bool QwtCounter::event ( QEvent * e )
    00207 {
    00208 #if QT_VERSION >= 0x040000
    00209     if ( e->type() == QEvent::PolishRequest )
    00210         polish();
    00211 #endif
    00212     return QWidget::event(e);
    00213 }
    00214
    00236 void QwtCounter::keyPressEvent (QKeyEvent *e)
    00237 {
    00238     bool accepted = true;
    00239
    00240     switch ( e->key() )
    00241     {
    00242         case Qt::Key_Home:
    00243 #if QT_VERSION >= 0x040000
    00244             if ( e->modifiers() & Qt::ControlModifier )
    00245 #else
    00246             if ( e->state() & Qt::ControlButton )
    00247 #endif
    00248                 setValue(minValue());
    00249             else
    00250                 accepted = false;
    00251             break;
    00252         case Qt::Key_End:
    00253 #if QT_VERSION >= 0x040000
    00254             if ( e->modifiers() & Qt::ControlModifier )
    00255 #else
    00256             if ( e->state() & Qt::ControlButton )
    00257 #endif
    00258                 setValue(maxValue());
    00259             else
    00260                 accepted = false;
    00261             break;
    00262         case Qt::Key_Up:
    00263             incValue(d_data->increment[0]);
    00264             break;
    00265         case Qt::Key_Down:
    00266             incValue(-d_data->increment[0]);
    00267             break;
    00268         case Qt::Key_PageUp:
    00269         case Qt::Key_PageDown:
    00270         {
    00271             int increment = d_data->increment[0];
    00272             if ( d_data->nButtons >= 2 )
    00273                 increment = d_data->increment[1];
    00274             if ( d_data->nButtons >= 3 )
    00275             {
    00276 #if QT_VERSION >= 0x040000
    00277                 if ( e->modifiers() & Qt::ShiftModifier )
    00278 #else
    00279                 if ( e->state() & Qt::ShiftButton )
    00280 #endif
    00281                     increment = d_data->increment[2];
    00282             }
    00283             if ( e->key() == Qt::Key_PageDown )
    00284                 increment = -increment;
    00285             incValue(increment);
    00286             break;
    00287         }
    00288         default:
    00289             accepted = false;
    00290     }
    00291
    00292     if ( accepted )
    00293     {
    00294         e->accept();
    00295         return;
    00296     }
    00297
    00298     QWidget::keyPressEvent (e);
    00299 }
    00300
    00301 void QwtCounter::wheelEvent(QWheelEvent *e)
    00302 {
    00303     e->accept();
    00304
    00305     if ( d_data->nButtons <= 0 )
    00306         return;
    00307
    00308     int increment = d_data->increment[0];
    00309     if ( d_data->nButtons >= 2 )
    00310     {
    00311 #if QT_VERSION >= 0x040000
    00312         if ( e->modifiers() & Qt::ControlModifier )
    00313 #else
    00314         if ( e->state() & Qt::ControlButton )
    00315 #endif
    00316             increment = d_data->increment[1];
    00317     }
    00318     if ( d_data->nButtons >= 3 )
    00319     {
    00320 #if QT_VERSION >= 0x040000
    00321         if ( e->modifiers() & Qt::ShiftModifier )
    00322 #else
    00323         if ( e->state() & Qt::ShiftButton )
    00324 #endif
    00325             increment = d_data->increment[2];
    00326     }
    00327
    00328     for ( int i = 0; i < d_data->nButtons; i++ )
    00329     {
    00330         if ( d_data->buttonDown[i]->geometry().contains(e->pos()) ||
    00331             d_data->buttonUp[i]->geometry().contains(e->pos()) )
    00332         {
    00333             increment = d_data->increment[i];
    00334         }
    00335     }
    00336
    00337     const int wheel_delta = 120;
    00338
    00339     int delta = e->delta();
    00340     if ( delta >= 2 * wheel_delta )
    00341         delta /= 2; // Never saw an abs(delta) < 240
    00342
    00343     incValue(delta / wheel_delta * increment);
    00344 }
    00345
    00355 void QwtCounter::setIncSteps(QwtCounter::Button btn, int nSteps)
    00356 {
    00357     if (( btn >= 0) && (btn < ButtonCnt))
    00358        d_data->increment[btn] = nSteps;
    00359 }
    00360
    00367 int QwtCounter::incSteps(QwtCounter::Button btn) const
    00368 {
    00369     if (( btn >= 0) && (btn < ButtonCnt))
    00370        return d_data->increment[btn];
    00371
    00372     return 0;
    00373 }
    00374
    00382 void QwtCounter::setValue(double v)
    00383 {
    00384     QwtDoubleRange::setValue(v);
    00385
    00386     showNum(value());
    00387     updateButtons();
    00388 }
    00389
    00393 void QwtCounter::valueChange()
    00394 {
    00395     if ( isValid() )
    00396         showNum(value());
    00397     else
    00398         d_data->valueEdit->setText(QString::null);
    00399
    00400     updateButtons();
    00401
    00402     if ( isValid() )
    00403         emit valueChanged(value());
    00404 }
    00405
    00414 void QwtCounter::updateButtons()
    00415 {
    00416     if ( isValid() )
    00417     {
    00418         // 1. save enabled state of the smallest down- and up-button
    00419         // 2. change enabled state on under- or over-flow
    00420
    00421         for ( int i = 0; i < ButtonCnt; i++ )
    00422         {
    00423             d_data->buttonDown[i]->setEnabled(value() > minValue());
    00424             d_data->buttonUp[i]->setEnabled(value() < maxValue());
    00425         }
    00426     }
    00427     else
    00428     {
    00429         for ( int i = 0; i < ButtonCnt; i++ )
    00430         {
    00431             d_data->buttonDown[i]->setEnabled(false);
    00432             d_data->buttonUp[i]->setEnabled(false);
    00433         }
    00434     }
    00435 }
    00436
    00441 void QwtCounter::setNumButtons(int n)
    00442 {
    00443     if ( n<0 || n>ButtonCnt )
    00444         return;
    00445
    00446     for ( int i = 0; i < ButtonCnt; i++ )
    00447     {
    00448         if ( i < n )
    00449         {
    00450             d_data->buttonDown[i]->show();
    00451             d_data->buttonUp[i]->show();
    00452         }
    00453         else
    00454         {
    00455             d_data->buttonDown[i]->hide();
    00456             d_data->buttonUp[i]->hide();
    00457         }
    00458     }
    00459
    00460     d_data->nButtons = n;
    00461 }
    00462
    00466 int QwtCounter::numButtons() const
    00467 {
    00468     return d_data->nButtons;
    00469 }
    00470
    00472 void QwtCounter::showNum(double d)
    00473 {
    00474     QString v;
    00475     v.setNum(d);
    00476
    00477     const int cursorPos = d_data->valueEdit->cursorPosition();
    00478     d_data->valueEdit->setText(v);
    00479     d_data->valueEdit->setCursorPosition(cursorPos);
    00480 }
    00481
    00483 void QwtCounter::btnClicked()
    00484 {
    00485     for ( int i = 0; i < ButtonCnt; i++ )
    00486     {
    00487         if ( d_data->buttonUp[i] == sender() )
    00488             incValue(d_data->increment[i]);
    00489
    00490         if ( d_data->buttonDown[i] == sender() )
    00491             incValue(-d_data->increment[i]);
    00492     }
    00493 }
    00494
    00496 void QwtCounter::btnReleased()
    00497 {
    00498     emit buttonReleased(value());
    00499 }
    00500
    00507 void QwtCounter::rangeChange()
    00508 {
    00509     updateButtons();
    00510 }
    00511
    00513 QSize QwtCounter::sizeHint() const
    00514 {
    00515     QString tmp;
    00516
    00517     int w = tmp.setNum(minValue()).length();
    00518     int w1 = tmp.setNum(maxValue()).length();
    00519     if ( w1 > w )
    00520         w = w1;
    00521     w1 = tmp.setNum(minValue() + step()).length();
    00522     if ( w1 > w )
    00523         w = w1;
    00524     w1 = tmp.setNum(maxValue() - step()).length();
    00525     if ( w1 > w )
    00526         w = w1;
    00527
    00528     tmp.fill('9', w);
    00529
    00530     QFontMetrics fm(d_data->valueEdit->font());
    00531     w = fm.width(tmp) + 2;
    00532 #if QT_VERSION >= 0x040000
    00533     if ( d_data->valueEdit->hasFrame() )
    00534         w += 2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
    00535 #else
    00536     w += 2 * d_data->valueEdit->frameWidth();
    00537 #endif
    00538
    00539     // Now we replace default sizeHint contribution of d_data->valueEdit by
    00540     // what we really need.
    00541
    00542     w += QWidget::sizeHint().width() - d_data->valueEdit->sizeHint().width();
    00543
    00544     const int h = qwtMin(QWidget::sizeHint().height(),
    00545         d_data->valueEdit->minimumSizeHint().height());
    00546     return QSize(w, h);
    00547 }
    00548
    00550 double QwtCounter::step() const
    00551 {
    00552     return QwtDoubleRange::step();
    00553 }
    00554
    00556 void QwtCounter::setStep(double s)
    00557 {
    00558     QwtDoubleRange::setStep(s);
    00559 }
    00560
    00562 double QwtCounter::minVal() const
    00563 {
    00564     return minValue();
    00565 }
    00566
    00568 void QwtCounter::setMinValue(double m)
    00569 {
    00570     setRange(m, maxValue(), step());
    00571 }
    00572
    00574 double QwtCounter::maxVal() const
    00575 {
    00576     return QwtDoubleRange::maxValue();
    00577 }
    00578
    00580 void QwtCounter::setMaxValue(double m)
    00581 {
    00582     setRange(minValue(), m, step());
    00583 }
    00584
    00586 void QwtCounter::setStepButton1(int nSteps)
    00587 {
    00588     setIncSteps(Button1, nSteps);
    00589 }
    00590
    00592 int QwtCounter::stepButton1() const
    00593 {
    00594     return incSteps(Button1);
    00595 }
    00596
    00598 void QwtCounter::setStepButton2(int nSteps)
    00599 {
    00600     setIncSteps(Button2, nSteps);
    00601 }
    00602
    00604 int QwtCounter::stepButton2() const
    00605 {
    00606     return incSteps(Button2);
    00607 }
    00608
    00610 void QwtCounter::setStepButton3(int nSteps)
    00611 {
    00612     setIncSteps(Button3, nSteps);
    00613 }
    00614
    00616 int QwtCounter::stepButton3() const
    00617 {
    00618     return incSteps(Button3);
    00619 }
    00620
    00621 double QwtCounter::value() const
    00622 {
    00623     return QwtDoubleRange::value();
    00624 }
    00625