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 

Generated on Mon Feb 26 21:22:36 2007 for Qwt User's Guide by  doxygen 1.4.6