kalarm/lib
spinbox.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <kdeversion.h>
00022 #include <kdebug.h>
00023
00024 #include <QLineEdit>
00025 #include <QObject>
00026 #include <QApplication>
00027 #include <QStyle>
00028 #include <QStyleOptionSpinBox>
00029 #include <QPainter>
00030 #include <QMouseEvent>
00031 #include <QKeyEvent>
00032 #include <QEvent>
00033
00034 #include "spinbox.moc"
00035
00036
00037 SpinBox::SpinBox(QWidget* parent)
00038 : QSpinBox(parent),
00039 mMinValue(QSpinBox::minimum()),
00040 mMaxValue(QSpinBox::maximum())
00041 {
00042 setRange(0, 99999);
00043 init();
00044 }
00045
00046 SpinBox::SpinBox(int minValue, int maxValue, QWidget* parent)
00047 : QSpinBox(parent),
00048 mMinValue(minValue),
00049 mMaxValue(maxValue)
00050 {
00051 setRange(minValue, maxValue);
00052 init();
00053 }
00054
00055 void SpinBox::init()
00056 {
00057 int step = QSpinBox::singleStep();
00058 mLineStep = step;
00059 mLineShiftStep = step;
00060 mCurrentButton = NO_BUTTON;
00061 mShiftMouse = false;
00062 mShiftMinBound = false;
00063 mShiftMaxBound = false;
00064 mSelectOnStep = true;
00065 mUpDownOnly = false;
00066 mReadOnly = false;
00067 mSuppressSignals = false;
00068 mEdited = false;
00069
00070 lineEdit()->installEventFilter(this);
00071
00072
00073 connect(lineEdit(), SIGNAL(textChanged(const QString&)), SLOT(textEdited()));
00074 connect(this, SIGNAL(valueChanged(int)), SLOT(valueChange()));
00075 }
00076
00077 void SpinBox::setReadOnly(bool ro)
00078 {
00079 if ((int)ro != (int)mReadOnly)
00080 {
00081 mReadOnly = ro;
00082 lineEdit()->setReadOnly(ro);
00083 if (ro)
00084 setShiftStepping(false);
00085 }
00086 }
00087
00088 int SpinBox::bound(int val) const
00089 {
00090 return (val < mMinValue) ? mMinValue : (val > mMaxValue) ? mMaxValue : val;
00091 }
00092
00093 void SpinBox::setMinimum(int val)
00094 {
00095 mMinValue = val;
00096 QSpinBox::setMinimum(val);
00097 mShiftMinBound = false;
00098 }
00099
00100 void SpinBox::setMaximum(int val)
00101 {
00102 mMaxValue = val;
00103 QSpinBox::setMaximum(val);
00104 mShiftMaxBound = false;
00105 }
00106
00107 void SpinBox::setSingleStep(int step)
00108 {
00109 mLineStep = step;
00110 if (!mShiftMouse)
00111 QSpinBox::setSingleStep(step);
00112 }
00113
00114 void SpinBox::setSingleShiftStep(int step)
00115 {
00116 mLineShiftStep = step;
00117 if (mShiftMouse)
00118 QSpinBox::setSingleStep(step);
00119 }
00120
00121 void SpinBox::stepBy(int steps)
00122 {
00123 int increment = steps * QSpinBox::singleStep();
00124 addValue(increment);
00125 emit stepped(increment);
00126 }
00127
00128
00129
00130
00131
00132
00133 void SpinBox::addValue(int change, bool current)
00134 {
00135 int newval = value() + change;
00136 int maxval = current ? QSpinBox::maximum() : mMaxValue;
00137 int minval = current ? QSpinBox::minimum() : mMinValue;
00138 if (wrapping())
00139 {
00140 int range = maxval - minval + 1;
00141 if (newval > maxval)
00142 newval = minval + (newval - maxval - 1) % range;
00143 else if (newval < minval)
00144 newval = maxval - (minval - 1 - newval) % range;
00145 }
00146 else
00147 {
00148 if (newval > maxval)
00149 newval = maxval;
00150 else if (newval < minval)
00151 newval = minval;
00152 }
00153 setValue(newval);
00154 }
00155
00156 void SpinBox::valueChange()
00157 {
00158 if (!mSuppressSignals)
00159 {
00160 int val = value();
00161 if (mShiftMinBound && val >= mMinValue)
00162 {
00163
00164 QSpinBox::setMinimum(mMinValue);
00165 mShiftMinBound = false;
00166 }
00167 if (mShiftMaxBound && val <= mMaxValue)
00168 {
00169
00170 QSpinBox::setMaximum(mMaxValue);
00171 mShiftMaxBound = false;
00172 }
00173
00174 if (!mSelectOnStep && hasFocus())
00175 lineEdit()->deselect();
00176 }
00177 }
00178
00179
00180
00181
00182 void SpinBox::textEdited()
00183 {
00184 mEdited = true;
00185 }
00186
00187
00188
00189
00190 bool SpinBox::eventFilter(QObject* obj, QEvent* e)
00191 {
00192 if (obj == lineEdit())
00193 {
00194 if (e->type() == QEvent::KeyPress)
00195 {
00196
00197 QKeyEvent* ke = (QKeyEvent*)e;
00198 int key = ke->key();
00199 if (key == Qt::Key_Up || key == Qt::Key_Down)
00200 {
00201 if (mReadOnly)
00202 return true;
00203 int step;
00204 if ((ke->modifiers() & (Qt::ShiftModifier | Qt::AltModifier)) == Qt::ShiftModifier)
00205 {
00206
00207 int val = value();
00208 if (key == Qt::Key_Up)
00209 step = mLineShiftStep - val % mLineShiftStep;
00210 else
00211 step = - ((val + mLineShiftStep - 1) % mLineShiftStep + 1);
00212 }
00213 else
00214 step = (key == Qt::Key_Up) ? mLineStep : -mLineStep;
00215 addValue(step, false);
00216 return true;
00217 }
00218 }
00219 }
00220 return QSpinBox::eventFilter(obj, e);
00221 }
00222
00223 void SpinBox::focusOutEvent(QFocusEvent* e)
00224 {
00225 if (mEdited)
00226 {
00227 interpretText();
00228 mEdited = false;
00229 }
00230 QSpinBox::focusOutEvent(e);
00231 }
00232
00233 void SpinBox::mousePressEvent(QMouseEvent* e)
00234 {
00235 if (!clickEvent(e))
00236 QSpinBox::mousePressEvent(e);
00237 }
00238
00239 void SpinBox::mouseDoubleClickEvent(QMouseEvent* e)
00240 {
00241 if (!clickEvent(e))
00242 QSpinBox::mouseDoubleClickEvent(e);
00243 }
00244
00245 bool SpinBox::clickEvent(QMouseEvent* e)
00246 {
00247 if (e->button() == Qt::LeftButton)
00248 {
00249
00250 if (mReadOnly)
00251 return true;
00252 mCurrentButton = whichButton(e->pos());
00253 if (mCurrentButton == NO_BUTTON)
00254 {
00255 e->accept();
00256 return true;
00257 }
00258 bool shift = (e->modifiers() & (Qt::ShiftModifier | Qt::AltModifier)) == Qt::ShiftModifier;
00259 if (setShiftStepping(shift))
00260 {
00261 e->accept();
00262 return true;
00263 }
00264 }
00265 return false;
00266 }
00267
00268 void SpinBox::mouseReleaseEvent(QMouseEvent* e)
00269 {
00270 if (e->button() == Qt::LeftButton && mShiftMouse)
00271 setShiftStepping(false);
00272 QSpinBox::mouseReleaseEvent(e);
00273 }
00274
00275 void SpinBox::mouseMoveEvent(QMouseEvent* e)
00276 {
00277 if (e->buttons() & Qt::LeftButton)
00278 {
00279
00280 if (mReadOnly)
00281 return;
00282 int newButton = whichButton(e->pos());
00283 if (newButton != mCurrentButton)
00284 {
00285
00286
00287 mCurrentButton = newButton;
00288 bool shift = (e->modifiers() & (Qt::ShiftModifier | Qt::AltModifier)) == Qt::ShiftModifier;
00289 if (setShiftStepping(shift))
00290 {
00291 e->accept();
00292 return;
00293 }
00294 }
00295 }
00296 QSpinBox::mouseMoveEvent(e);
00297 }
00298
00299 void SpinBox::keyPressEvent(QKeyEvent* e)
00300 {
00301 if (!keyEvent(e))
00302 QSpinBox::keyPressEvent(e);
00303 }
00304
00305 void SpinBox::keyReleaseEvent(QKeyEvent* e)
00306 {
00307 if (!keyEvent(e))
00308 QSpinBox::keyReleaseEvent(e);
00309 }
00310
00311 bool SpinBox::keyEvent(QKeyEvent* e)
00312 {
00313 int key = e->key();
00314 int state = e->modifiers();
00315 if ((QApplication::mouseButtons() & Qt::LeftButton)
00316 && (key == Qt::Key_Shift || key == Qt::Key_Alt))
00317 {
00318
00319 if (mReadOnly)
00320 return true;
00321 bool shift = (state & (Qt::ShiftModifier | Qt::AltModifier)) == Qt::ShiftModifier;
00322 if ((!shift && mShiftMouse) || (shift && !mShiftMouse))
00323 {
00324
00325
00326 if (setShiftStepping(shift))
00327 {
00328 e->accept();
00329 return true;
00330 }
00331 }
00332 }
00333 return false;
00334 }
00335
00336
00337
00338
00339 bool SpinBox::setShiftStepping(bool shift)
00340 {
00341 if (mCurrentButton == NO_BUTTON)
00342 shift = false;
00343 if (shift && !mShiftMouse)
00344 {
00345
00346
00347
00348
00349
00350 int val = value();
00351 int step = (mCurrentButton == UP) ? mLineShiftStep : (mCurrentButton == DOWN) ? -mLineShiftStep : 0;
00352 int adjust = shiftStepAdjustment(val, step);
00353 mShiftMouse = true;
00354 if (adjust)
00355 {
00356
00357
00358
00359
00360
00361
00362 if (!wrapping())
00363 {
00364
00365
00366
00367 int newval = val + adjust + step;
00368 int svt = specialValueText().isEmpty() ? 0 : 1;
00369 int minval = mMinValue + svt;
00370 if (newval <= minval || newval >= mMaxValue)
00371 {
00372
00373 if (svt && newval <= mMinValue && val == mMinValue)
00374 newval = mMinValue;
00375 else
00376 newval = (newval <= minval) ? minval : mMaxValue;
00377 QSpinBox::setValue(newval);
00378 emit stepped(step);
00379 return true;
00380 }
00381
00382
00383
00384 int tempval = val + adjust;
00385 if (tempval < mMinValue)
00386 {
00387 QSpinBox::setMinimum(tempval);
00388 mShiftMinBound = true;
00389 }
00390 else if (tempval > mMaxValue)
00391 {
00392 QSpinBox::setMaximum(tempval);
00393 mShiftMaxBound = true;
00394 }
00395 }
00396
00397
00398 mSuppressSignals = true;
00399 bool blocked = signalsBlocked();
00400 blockSignals(true);
00401 addValue(adjust, true);
00402 blockSignals(blocked);
00403 mSuppressSignals = false;
00404 }
00405 QSpinBox::setSingleStep(mLineShiftStep);
00406 }
00407 else if (!shift && mShiftMouse)
00408 {
00409
00410 QSpinBox::setSingleStep(mLineStep);
00411 QSpinBox::setMinimum(mMinValue);
00412 QSpinBox::setMaximum(mMaxValue);
00413 mShiftMinBound = mShiftMaxBound = false;
00414 mShiftMouse = false;
00415 }
00416 return false;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 int SpinBox::shiftStepAdjustment(int oldValue, int shiftStep)
00431 {
00432 if (oldValue == 0 || shiftStep == 0)
00433 return 0;
00434 if (shiftStep > 0)
00435 {
00436 if (oldValue >= 0)
00437 return -(oldValue % shiftStep);
00438 else
00439 return (-oldValue - 1) % shiftStep + 1 - shiftStep;
00440 }
00441 else
00442 {
00443 shiftStep = -shiftStep;
00444 if (oldValue >= 0)
00445 return shiftStep - ((oldValue - 1) % shiftStep + 1);
00446 else
00447 return (-oldValue) % shiftStep;
00448 }
00449 }
00450
00451
00452
00453
00454 int SpinBox::whichButton(const QPoint& pos)
00455 {
00456 QStyleOptionSpinBox option;
00457 initStyleOption(option);
00458 if (style()->subControlRect(QStyle::CC_SpinBox, &option, QStyle::SC_SpinBoxUp).contains(pos))
00459 return UP;
00460 if (style()->subControlRect(QStyle::CC_SpinBox, &option, QStyle::SC_SpinBoxDown).contains(pos))
00461 return DOWN;
00462 return NO_BUTTON;
00463 }
00464
00465 QRect SpinBox::upRect() const
00466 {
00467 QStyleOptionSpinBox option;
00468 initStyleOption(option);
00469 return style()->subControlRect(QStyle::CC_SpinBox, &option, QStyle::SC_SpinBoxUp);
00470 }
00471
00472 QRect SpinBox::downRect() const
00473 {
00474 QStyleOptionSpinBox option;
00475 initStyleOption(option);
00476 return style()->subControlRect(QStyle::CC_SpinBox, &option, QStyle::SC_SpinBoxDown);
00477 }
00478
00479 QRect SpinBox::upDownRect() const
00480 {
00481 QStyleOptionSpinBox option;
00482 initStyleOption(option);
00483 return style()->subControlRect(QStyle::CC_SpinBox, &option, QStyle::SC_SpinBoxUp)
00484 | style()->subControlRect(QStyle::CC_SpinBox, &option, QStyle::SC_SpinBoxDown);
00485 }
00486
00487 void SpinBox::paintEvent(QPaintEvent* pe)
00488 {
00489 if (mUpDownOnly)
00490 {
00491 QStyleOptionSpinBox option;
00492 initStyleOption(option);
00493 QPainter painter(this);
00494 style()->drawComplexControl(QStyle::CC_SpinBox, &option, &painter, this);
00495 }
00496 else
00497 QSpinBox::paintEvent(pe);
00498 }
00499
00500 void SpinBox::initStyleOption(QStyleOptionSpinBox& so) const
00501 {
00502 so.init(this);
00503
00504 so.subControls = mUpDownOnly ? QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown | QStyle::SC_SpinBoxFrame
00505 : QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown | QStyle::SC_SpinBoxFrame | QStyle::SC_SpinBoxEditField;
00506 so.buttonSymbols = buttonSymbols();
00507 so.frame = hasFrame();
00508 so.stepEnabled = stepEnabled();
00509 }