Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

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     d_data = new PrivateData;
00054 
00055 #if QT_VERSION >= 0x040000
00056     using namespace Qt;
00057 #endif
00058 
00059     QHBoxLayout *layout = new QHBoxLayout(this);
00060     layout->setSpacing(0);
00061     layout->setMargin(0);
00062 
00063     int i;
00064     for(i = ButtonCnt - 1; i >= 0; i--)
00065     {
00066         QwtArrowButton *btn =
00067             new QwtArrowButton(i+1, Qt::DownArrow,this);
00068         btn->setFocusPolicy(NoFocus);
00069         btn->installEventFilter(this);
00070         layout->addWidget(btn);
00071 
00072         connect(btn, SIGNAL(released()), SLOT(btnReleased()));
00073         connect(btn, SIGNAL(clicked()), SLOT(btnClicked()));
00074 
00075         d_data->buttonDown[i] = btn;
00076     }
00077 
00078     d_data->valueEdit = new QLineEdit(this);
00079     d_data->valueEdit->setReadOnly(false);
00080     d_data->valueEdit->setValidator(new QDoubleValidator(d_data->valueEdit));
00081     layout->addWidget(d_data->valueEdit);
00082 
00083 #if QT_VERSION >= 0x040000
00084     connect( d_data->valueEdit, SIGNAL(editingFinished()), 
00085         SLOT(textChanged()) );
00086 #else
00087     connect( d_data->valueEdit, SIGNAL(returnPressed()), SLOT(textChanged()) );
00088     connect( d_data->valueEdit, SIGNAL(lostFocus()), SLOT(textChanged()) );
00089 #endif
00090 
00091     layout->setStretchFactor(d_data->valueEdit, 10);
00092 
00093     for(i = 0; i < ButtonCnt; i++)
00094     {
00095 #if QT_VERSION >= 0x040000
00096         using namespace Qt;
00097 #endif
00098         QwtArrowButton *btn =
00099             new QwtArrowButton(i+1, Qt::UpArrow, this);
00100         btn->setFocusPolicy(NoFocus);
00101         btn->installEventFilter(this);
00102         layout->addWidget(btn);
00103 
00104         connect(btn, SIGNAL(released()), SLOT(btnReleased()));
00105         connect(btn, SIGNAL(clicked()), SLOT(btnClicked()));
00106     
00107         d_data->buttonUp[i] = btn;
00108     }
00109 
00110     setNumButtons(2);
00111     setRange(0.0,1.0,0.001);
00112     setValue(0.0);
00113 
00114     setSizePolicy(
00115         QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
00116 
00117     setFocusProxy(d_data->valueEdit);
00118     setFocusPolicy(StrongFocus);
00119 }
00120 
00121 QwtCounter::~QwtCounter()
00122 {
00123     delete d_data;
00124 }
00125 
00129 void QwtCounter::polish()
00130 {
00131     const int w = d_data->valueEdit->fontMetrics().width("W") + 8;
00132 
00133     for ( int i = 0; i < ButtonCnt; i++ )
00134     {
00135         d_data->buttonDown[i]->setMinimumWidth(w);
00136         d_data->buttonUp[i]->setMinimumWidth(w);
00137     }
00138 
00139 #if QT_VERSION < 0x040000
00140     QWidget::polish();
00141 #endif
00142 }
00143 
00145 void QwtCounter::textChanged() 
00146 {
00147     if ( !d_data->editable ) 
00148         return;
00149 
00150     bool converted = false;
00151 
00152     const double value = d_data->valueEdit->text().toDouble(&converted);
00153     if ( converted ) 
00154        setValue( value );
00155 }
00156 
00163 void QwtCounter::setEditable(bool editable)
00164 {
00165 #if QT_VERSION >= 0x040000
00166     using namespace Qt;
00167 #endif
00168     if ( editable == d_data->editable ) 
00169         return;
00170 
00171     d_data->editable = editable;
00172     d_data->valueEdit->setReadOnly(!editable);
00173 }
00174 
00176 bool QwtCounter::editable() const 
00177 {   
00178     return d_data->editable;
00179 }
00180 
00184 bool QwtCounter::event ( QEvent * e ) 
00185 {
00186 #if QT_VERSION >= 0x040000
00187     if ( e->type() == QEvent::PolishRequest )
00188         polish();
00189 #endif
00190     return QWidget::event(e);
00191 }
00192 
00214 void QwtCounter::keyPressEvent (QKeyEvent *e)
00215 {
00216     bool accepted = true;
00217 
00218     switch ( e->key() )
00219     {
00220         case Qt::Key_Home:
00221 #if QT_VERSION >= 0x040000
00222             if ( e->modifiers() & Qt::ControlModifier )
00223 #else
00224             if ( e->state() & Qt::ControlButton )
00225 #endif
00226                 setValue(minValue());
00227             else
00228                 accepted = false;
00229             break;
00230         case Qt::Key_End:
00231 #if QT_VERSION >= 0x040000
00232             if ( e->modifiers() & Qt::ControlModifier )
00233 #else
00234             if ( e->state() & Qt::ControlButton )
00235 #endif
00236                 setValue(maxValue());
00237             else
00238                 accepted = false;
00239             break;
00240         case Qt::Key_Up:
00241             incValue(d_data->increment[0]);
00242             break;
00243         case Qt::Key_Down:
00244             incValue(-d_data->increment[0]);
00245             break;
00246         case Qt::Key_PageUp:
00247         case Qt::Key_PageDown:
00248         {
00249             int increment = d_data->increment[0];
00250             if ( d_data->nButtons >= 2 )
00251                 increment = d_data->increment[1];
00252             if ( d_data->nButtons >= 3 )
00253             {
00254 #if QT_VERSION >= 0x040000
00255                 if ( e->modifiers() & Qt::ShiftModifier )
00256 #else
00257                 if ( e->state() & Qt::ShiftButton )
00258 #endif
00259                     increment = d_data->increment[2];
00260             }
00261             if ( e->key() == Qt::Key_PageDown )
00262                 increment = -increment;
00263             incValue(increment);
00264             break;
00265         }
00266         default:
00267             accepted = false;
00268     }
00269 
00270     if ( accepted )
00271     {
00272         e->accept();
00273         return;
00274     }
00275 
00276     QWidget::keyPressEvent (e);
00277 }
00278 
00279 void QwtCounter::wheelEvent(QWheelEvent *e)
00280 {
00281     e->accept();
00282 
00283     if ( d_data->nButtons <= 0 )
00284         return;
00285 
00286     int increment = d_data->increment[0];
00287     if ( d_data->nButtons >= 2 )
00288     {
00289 #if QT_VERSION >= 0x040000
00290         if ( e->modifiers() & Qt::ControlModifier )
00291 #else
00292         if ( e->state() & Qt::ControlButton )
00293 #endif
00294             increment = d_data->increment[1];
00295     }
00296     if ( d_data->nButtons >= 3 )
00297     {
00298 #if QT_VERSION >= 0x040000
00299         if ( e->modifiers() & Qt::ShiftModifier )
00300 #else
00301         if ( e->state() & Qt::ShiftButton )
00302 #endif
00303             increment = d_data->increment[2];
00304     }
00305         
00306     for ( int i = 0; i < d_data->nButtons; i++ )
00307     {
00308         if ( d_data->buttonDown[i]->geometry().contains(e->pos()) ||
00309             d_data->buttonUp[i]->geometry().contains(e->pos()) )
00310         {
00311             increment = d_data->increment[i];
00312         }
00313     }
00314 
00315     const int wheel_delta = 120;
00316 
00317     int delta = e->delta();
00318     if ( delta >= 2 * wheel_delta )
00319         delta /= 2; // Never saw an abs(delta) < 240
00320 
00321     incValue(delta / wheel_delta * increment);
00322 }
00323 
00333 void QwtCounter::setIncSteps(QwtCounter::Button btn, int nSteps)
00334 {
00335     if (( btn >= 0) && (btn < ButtonCnt))
00336        d_data->increment[btn] = nSteps;
00337 }
00338 
00345 int QwtCounter::incSteps(QwtCounter::Button btn) const
00346 {
00347     if (( btn >= 0) && (btn < ButtonCnt))
00348        return d_data->increment[btn];
00349 
00350     return 0;
00351 }
00352 
00360 void QwtCounter::setValue(double v)
00361 {
00362     QwtDoubleRange::setValue(v);
00363 
00364     showNum(value());
00365     updateButtons();
00366 }
00367 
00371 void QwtCounter::valueChange()
00372 {
00373     if ( isValid() )
00374         showNum(value());
00375     else
00376         d_data->valueEdit->setText(QString::null);
00377 
00378     updateButtons();
00379 
00380     if ( isValid() )
00381         emit valueChanged(value());
00382 }
00383 
00392 void QwtCounter::updateButtons()
00393 {
00394     if ( isValid() )
00395     {
00396         // 1. save enabled state of the smallest down- and up-button
00397         // 2. change enabled state on under- or over-flow
00398 
00399         for ( int i = 0; i < ButtonCnt; i++ )
00400         {
00401             d_data->buttonDown[i]->setEnabled(value() > minValue());
00402             d_data->buttonUp[i]->setEnabled(value() < maxValue());
00403         }
00404     }
00405     else
00406     {
00407         for ( int i = 0; i < ButtonCnt; i++ )
00408         {
00409             d_data->buttonDown[i]->setEnabled(false);
00410             d_data->buttonUp[i]->setEnabled(false);
00411         }
00412     }
00413 }
00414 
00419 void QwtCounter::setNumButtons(int n)
00420 {
00421     if ( n<0 || n>ButtonCnt )
00422         return;
00423 
00424     for ( int i = 0; i < ButtonCnt; i++ )
00425     {
00426         if ( i < n )
00427         {
00428             d_data->buttonDown[i]->show();
00429             d_data->buttonUp[i]->show();
00430         }
00431         else
00432         {
00433             d_data->buttonDown[i]->hide();
00434             d_data->buttonUp[i]->hide();
00435         }
00436     }
00437 
00438     d_data->nButtons = n;
00439 }
00440 
00444 int QwtCounter::numButtons() const 
00445 { 
00446     return d_data->nButtons; 
00447 }
00448 
00450 void QwtCounter::showNum(double d)
00451 {
00452     QString v;
00453     v.setNum(d);
00454 
00455     const int cursorPos = d_data->valueEdit->cursorPosition();
00456     d_data->valueEdit->setText(v);
00457     d_data->valueEdit->setCursorPosition(cursorPos);
00458 }
00459 
00461 void QwtCounter::btnClicked()
00462 {
00463     for ( int i = 0; i < ButtonCnt; i++ )
00464     {
00465         if ( d_data->buttonUp[i] == sender() )
00466             incValue(d_data->increment[i]);
00467 
00468         if ( d_data->buttonDown[i] == sender() )
00469             incValue(-d_data->increment[i]);
00470     }
00471 }
00472 
00474 void QwtCounter::btnReleased()
00475 {
00476     emit buttonReleased(value());
00477 }
00478 
00485 void QwtCounter::rangeChange()
00486 {
00487     updateButtons();
00488 }
00489 
00491 QSize QwtCounter::sizeHint() const
00492 {
00493     QString tmp;
00494 
00495     int w = tmp.setNum(minValue()).length();
00496     int w1 = tmp.setNum(maxValue()).length();
00497     if ( w1 > w )
00498         w = w1;
00499     w1 = tmp.setNum(minValue() + step()).length();
00500     if ( w1 > w )
00501         w = w1;
00502     w1 = tmp.setNum(maxValue() - step()).length();
00503     if ( w1 > w )
00504         w = w1;
00505 
00506     tmp.fill('9', w);
00507 
00508     QFontMetrics fm(d_data->valueEdit->font());
00509     w = fm.width(tmp) + 2;
00510 #if QT_VERSION >= 0x040000
00511     if ( d_data->valueEdit->hasFrame() )
00512         w += 2 * style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
00513 #else
00514     w += 2 * d_data->valueEdit->frameWidth(); 
00515 #endif
00516 
00517     // Now we replace default sizeHint contribution of d_data->valueEdit by
00518     // what we really need.
00519 
00520     w += QWidget::sizeHint().width() - d_data->valueEdit->sizeHint().width();
00521 
00522     const int h = qwtMin(QWidget::sizeHint().height(), 
00523         d_data->valueEdit->minimumSizeHint().height());
00524     return QSize(w, h);
00525 }
00526 
00528 double QwtCounter::step() const
00529 {
00530     return QwtDoubleRange::step();
00531 }
00532     
00534 void QwtCounter::setStep(double s)
00535 {
00536     QwtDoubleRange::setStep(s);
00537 }
00538 
00540 double QwtCounter::minVal() const
00541 {
00542     return minValue();
00543 }
00544 
00546 void QwtCounter::setMinValue(double m)
00547 {
00548     setRange(m, maxValue(), step());
00549 }
00550 
00552 double QwtCounter::maxVal() const
00553 {
00554     return QwtDoubleRange::maxValue();
00555 }
00556 
00558 void QwtCounter::setMaxValue(double m)
00559 {
00560     setRange(minValue(), m, step());
00561 }
00562 
00564 void QwtCounter::setStepButton1(int nSteps)
00565 {
00566     setIncSteps(Button1, nSteps);
00567 }
00568 
00570 int QwtCounter::stepButton1() const
00571 {
00572     return incSteps(Button1);
00573 }
00574 
00576 void QwtCounter::setStepButton2(int nSteps)
00577 {
00578     setIncSteps(Button2, nSteps);
00579 }
00580 
00582 int QwtCounter::stepButton2() const
00583 {
00584     return incSteps(Button2);
00585 }
00586 
00588 void QwtCounter::setStepButton3(int nSteps)
00589 {
00590     setIncSteps(Button3, nSteps);
00591 }
00592 
00594 int QwtCounter::stepButton3() const
00595 {
00596     return incSteps(Button3);
00597 }
00598 
00599 double QwtCounter::value() const
00600 {
00601     return QwtDoubleRange::value();
00602 }
00603 

Generated on Mon Jan 30 22:16:25 2006 for Qwt User's Guide by  doxygen 1.4.4