00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qglobal.h>
00022
00023 #include <stdlib.h>
00024
00025 #include <qstyle.h>
00026 #include <qobjectlist.h>
00027 #include <qapplication.h>
00028 #include <qpixmap.h>
00029 #include <qcursor.h>
00030 #include <qtimer.h>
00031 #include <qwmatrix.h>
00032
00033 #include "spinbox2.moc"
00034 #include "spinbox2private.moc"
00035
00036
00037
00038
00039
00040
00041
00042 static const char* mirrorStyles[] = {
00043 "PlastikStyle",
00044 0
00045 };
00046 static bool mirrorStyle(const QStyle&);
00047
00048
00049 int SpinBox2::mReverseLayout = -1;
00050
00051 SpinBox2::SpinBox2(QWidget* parent, const char* name)
00052 : QFrame(parent, name),
00053 mReverseWithLayout(true)
00054 {
00055 mUpdown2Frame = new QFrame(this);
00056 mSpinboxFrame = new QFrame(this);
00057 mUpdown2 = new ExtraSpinBox(mUpdown2Frame, "updown2");
00058
00059 mSpinbox = new MainSpinBox(this, mSpinboxFrame);
00060 init();
00061 }
00062
00063 SpinBox2::SpinBox2(int minValue, int maxValue, int step, int step2, QWidget* parent, const char* name)
00064 : QFrame(parent, name),
00065 mReverseWithLayout(true)
00066 {
00067 mUpdown2Frame = new QFrame(this);
00068 mSpinboxFrame = new QFrame(this);
00069 mUpdown2 = new ExtraSpinBox(minValue, maxValue, step2, mUpdown2Frame, "updown2");
00070 mSpinbox = new MainSpinBox(minValue, maxValue, step, this, mSpinboxFrame);
00071 setSteps(step, step2);
00072 init();
00073 }
00074
00075 void SpinBox2::init()
00076 {
00077 if (mReverseLayout < 0)
00078 mReverseLayout = QApplication::reverseLayout() ? 1 : 0;
00079 mMinValue = mSpinbox->minValue();
00080 mMaxValue = mSpinbox->maxValue();
00081 mLineStep = mSpinbox->lineStep();
00082 mLineShiftStep = mSpinbox->lineShiftStep();
00083 mPageStep = mUpdown2->lineStep();
00084 mPageShiftStep = mUpdown2->lineShiftStep();
00085 mSpinbox->setSelectOnStep(false);
00086 mUpdown2->setSelectOnStep(false);
00087 setFocusProxy(mSpinbox);
00088 mUpdown2->setFocusPolicy(QWidget::NoFocus);
00089 mSpinMirror = new SpinMirror(mUpdown2, mUpdown2Frame, this);
00090 if (!mirrorStyle(style()))
00091 mSpinMirror->hide();
00092 connect(mSpinbox, SIGNAL(valueChanged(int)), SLOT(valueChange()));
00093 connect(mSpinbox, SIGNAL(valueChanged(int)), SIGNAL(valueChanged(int)));
00094 connect(mSpinbox, SIGNAL(valueChanged(const QString&)), SIGNAL(valueChanged(const QString&)));
00095 connect(mUpdown2, SIGNAL(stepped(int)), SLOT(stepPage(int)));
00096 connect(mUpdown2, SIGNAL(styleUpdated()), SLOT(updateMirror()));
00097 }
00098
00099 void SpinBox2::setReadOnly(bool ro)
00100 {
00101 if (static_cast<int>(ro) != static_cast<int>(mSpinbox->isReadOnly()))
00102 {
00103 mSpinbox->setReadOnly(ro);
00104 mUpdown2->setReadOnly(ro);
00105 mSpinMirror->setReadOnly(ro);
00106 }
00107 }
00108
00109 void SpinBox2::setReverseWithLayout(bool reverse)
00110 {
00111 if (reverse != mReverseWithLayout)
00112 {
00113 mReverseWithLayout = reverse;
00114 setSteps(mLineStep, mPageStep);
00115 setShiftSteps(mLineShiftStep, mPageShiftStep);
00116 }
00117 }
00118
00119 void SpinBox2::setEnabled(bool enabled)
00120 {
00121 QFrame::setEnabled(enabled);
00122 updateMirror();
00123 }
00124
00125 void SpinBox2::setWrapping(bool on)
00126 {
00127 mSpinbox->setWrapping(on);
00128 mUpdown2->setWrapping(on);
00129 }
00130
00131 QRect SpinBox2::up2Rect() const
00132 {
00133 return mUpdown2->upRect();
00134 }
00135
00136 QRect SpinBox2::down2Rect() const
00137 {
00138 return mUpdown2->downRect();
00139 }
00140
00141 void SpinBox2::setLineStep(int step)
00142 {
00143 mLineStep = step;
00144 if (reverseButtons())
00145 mUpdown2->setLineStep(step);
00146 else
00147 mSpinbox->setLineStep(step);
00148 }
00149
00150 void SpinBox2::setSteps(int line, int page)
00151 {
00152 mLineStep = line;
00153 mPageStep = page;
00154 if (reverseButtons())
00155 {
00156 mUpdown2->setLineStep(line);
00157 mSpinbox->setLineStep(page);
00158 }
00159 else
00160 {
00161 mSpinbox->setLineStep(line);
00162 mUpdown2->setLineStep(page);
00163 }
00164 }
00165
00166 void SpinBox2::setShiftSteps(int line, int page)
00167 {
00168 mLineShiftStep = line;
00169 mPageShiftStep = page;
00170 if (reverseButtons())
00171 {
00172 mUpdown2->setLineShiftStep(line);
00173 mSpinbox->setLineShiftStep(page);
00174 }
00175 else
00176 {
00177 mSpinbox->setLineShiftStep(line);
00178 mUpdown2->setLineShiftStep(page);
00179 }
00180 }
00181
00182 void SpinBox2::setButtonSymbols(QSpinBox::ButtonSymbols newSymbols)
00183 {
00184 if (mSpinbox->buttonSymbols() == newSymbols)
00185 return;
00186 mSpinbox->setButtonSymbols(newSymbols);
00187 mUpdown2->setButtonSymbols(newSymbols);
00188 }
00189
00190 int SpinBox2::bound(int val) const
00191 {
00192 return (val < mMinValue) ? mMinValue : (val > mMaxValue) ? mMaxValue : val;
00193 }
00194
00195 void SpinBox2::setMinValue(int val)
00196 {
00197 mMinValue = val;
00198 mSpinbox->setMinValue(val);
00199 mUpdown2->setMinValue(val);
00200 }
00201
00202 void SpinBox2::setMaxValue(int val)
00203 {
00204 mMaxValue = val;
00205 mSpinbox->setMaxValue(val);
00206 mUpdown2->setMaxValue(val);
00207 }
00208
00209 void SpinBox2::valueChange()
00210 {
00211 int val = mSpinbox->value();
00212 bool blocked = mUpdown2->signalsBlocked();
00213 mUpdown2->blockSignals(true);
00214 mUpdown2->setValue(val);
00215 mUpdown2->blockSignals(blocked);
00216 }
00217
00218
00219
00220
00221
00222
00223 void SpinBox2::showEvent(QShowEvent*)
00224 {
00225 arrange();
00226 }
00227
00228 QSize SpinBox2::sizeHint() const
00229 {
00230 getMetrics();
00231 QSize size = mSpinbox->sizeHint();
00232 size.setWidth(size.width() - xSpinbox + wUpdown2 + wGap);
00233 return size;
00234 }
00235
00236 QSize SpinBox2::minimumSizeHint() const
00237 {
00238 getMetrics();
00239 QSize size = mSpinbox->minimumSizeHint();
00240 size.setWidth(size.width() - xSpinbox + wUpdown2 + wGap);
00241 return size;
00242 }
00243
00244 void SpinBox2::styleChange(QStyle&)
00245 {
00246 if (mirrorStyle(style()))
00247 mSpinMirror->show();
00248 else
00249 mSpinMirror->hide();
00250 arrange();
00251 }
00252
00253
00254
00255
00256
00257 void SpinBox2::updateMirror()
00258 {
00259 mSpinMirror->setNormalButtons(QPixmap::grabWidget(mUpdown2Frame, 0, 0));
00260 }
00261
00262
00263
00264
00265 void SpinBox2::arrange()
00266 {
00267 getMetrics();
00268 QRect arrowRect = QStyle::visualRect(QRect(0, 0, wUpdown2, height()), this);
00269 mUpdown2Frame->setGeometry(arrowRect);
00270 mUpdown2->setGeometry(-xUpdown2, 0, mUpdown2->width(), height());
00271 mSpinboxFrame->setGeometry(QStyle::visualRect(QRect(wUpdown2 + wGap, 0, width() - wUpdown2 - wGap, height()), this));
00272 mSpinbox->setGeometry(-xSpinbox, 0, mSpinboxFrame->width() + xSpinbox, height());
00273 mSpinMirror->resize(wUpdown2, mUpdown2->height());
00274 mSpinMirror->setGeometry(arrowRect);
00275
00276 mSpinMirror->setNormalButtons(QPixmap::grabWidget(mUpdown2Frame, 0, 0));
00277 }
00278
00279
00280
00281
00282
00283 void SpinBox2::getMetrics() const
00284 {
00285 QRect rect = mUpdown2->style().querySubControlMetrics(QStyle::CC_SpinWidget, mUpdown2, QStyle::SC_SpinWidgetButtonField);
00286 if (style().inherits("PlastikStyle"))
00287 rect.setLeft(rect.left() - 1);
00288 xUpdown2 = mReverseLayout ? 0 : rect.left();
00289 wUpdown2 = mUpdown2->width() - rect.left();
00290 xSpinbox = mSpinbox->style().querySubControlMetrics(QStyle::CC_SpinWidget, mSpinbox, QStyle::SC_SpinWidgetEditField).left();
00291 wGap = 0;
00292
00293
00294 if (style().inherits("QMotifPlusStyle"))
00295 {
00296 xSpinbox = 0;
00297 wGap = 2;
00298 }
00299 }
00300
00301
00302
00303
00304
00305
00306 void SpinBox2::stepPage(int step)
00307 {
00308 if (abs(step) == mUpdown2->lineStep())
00309 mSpinbox->setValue(mUpdown2->value());
00310 else
00311 {
00312
00313 int oldValue = mSpinbox->value();
00314 if (!reverseButtons())
00315 {
00316
00317
00318
00319
00320 if (oldValue >= 0)
00321 oldValue -= oldValue % mUpdown2->lineStep();
00322 else
00323 oldValue += (-oldValue) % mUpdown2->lineStep();
00324 }
00325 int adjust = mSpinbox->shiftStepAdjustment(oldValue, step);
00326 if (adjust == -step
00327 && ((step > 0 && oldValue + step >= mSpinbox->maxValue())
00328 || (step < 0 && oldValue + step <= mSpinbox->minValue())))
00329 adjust = 0;
00330 mSpinbox->addValue(adjust + step);
00331 }
00332 bool focus = mSpinbox->selectOnStep() && mUpdown2->hasFocus();
00333 if (focus)
00334 mSpinbox->selectAll();
00335
00336
00337 mSpinMirror->redraw(QPixmap::grabWidget(mUpdown2Frame, 0, 0));
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 int SpinBox2::MainSpinBox::shiftStepAdjustment(int oldValue, int shiftStep)
00352 {
00353 if (owner->reverseButtons())
00354 {
00355
00356
00357
00358
00359 if (oldValue >= 0)
00360 oldValue -= oldValue % lineStep();
00361 else
00362 oldValue += (-oldValue) % lineStep();
00363 }
00364 return SpinBox::shiftStepAdjustment(oldValue, shiftStep);
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 void ExtraSpinBox::paintEvent(QPaintEvent* e)
00380 {
00381 SpinBox::paintEvent(e);
00382 if (mNewStylePending)
00383 {
00384 mNewStylePending = false;
00385 emit styleUpdated();
00386 }
00387 }
00388
00389
00390
00391
00392
00393
00394 SpinMirror::SpinMirror(SpinBox* spinbox, QFrame* spinFrame, QWidget* parent, const char* name)
00395 : QCanvasView(new QCanvas, parent, name),
00396 mSpinbox(spinbox),
00397 mSpinFrame(spinFrame),
00398 mReadOnly(false)
00399 {
00400 setVScrollBarMode(QScrollView::AlwaysOff);
00401 setHScrollBarMode(QScrollView::AlwaysOff);
00402 setFrameStyle(QFrame::NoFrame);
00403
00404
00405
00406 QObjectList* spinwidgets = spinbox->queryList("QSpinWidget", 0, false, true);
00407 mSpinWidget = (SpinBox*)spinwidgets->getFirst();
00408 delete spinwidgets;
00409 }
00410
00411 void SpinMirror::setNormalButtons(const QPixmap& px)
00412 {
00413 mNormalButtons = px;
00414 redraw(mNormalButtons);
00415 }
00416
00417 void SpinMirror::redraw()
00418 {
00419 redraw(QPixmap::grabWidget(mSpinFrame, 0, 0));
00420 }
00421
00422 void SpinMirror::redraw(const QPixmap& px)
00423 {
00424 QCanvas* c = canvas();
00425 c->setBackgroundPixmap(px);
00426 c->setAllChanged();
00427 c->update();
00428 }
00429
00430 void SpinMirror::resize(int w, int h)
00431 {
00432 canvas()->resize(w, h);
00433 QCanvasView::resize(w, h);
00434 resizeContents(w, h);
00435 setWorldMatrix(QWMatrix(-1, 0, 0, 1, w - 1, 0));
00436 }
00437
00438
00439
00440
00441 void SpinMirror::contentsMouseEvent(QMouseEvent* e)
00442 {
00443 if (mReadOnly)
00444 return;
00445 QPoint pt = contentsToViewport(e->pos());
00446 pt.setX(pt.x() + mSpinbox->upRect().left());
00447 QApplication::postEvent(mSpinWidget, new QMouseEvent(e->type(), pt, e->button(), e->state()));
00448
00449
00450 switch (e->type())
00451 {
00452 case QEvent::MouseButtonPress:
00453 case QEvent::MouseButtonRelease:
00454 QTimer::singleShot(0, this, SLOT(redraw()));
00455 break;
00456 default:
00457 break;
00458 }
00459 }
00460
00461
00462
00463
00464 void SpinMirror::contentsWheelEvent(QWheelEvent* e)
00465 {
00466 if (mReadOnly)
00467 return;
00468 QPoint pt = contentsToViewport(e->pos());
00469 pt.setX(pt.x() + mSpinbox->upRect().left());
00470 QApplication::postEvent(mSpinWidget, new QWheelEvent(pt, e->delta(), e->state(), e->orientation()));
00471 }
00472
00473
00474
00475
00476
00477 bool SpinMirror::event(QEvent* e)
00478 {
00479 switch (e->type())
00480 {
00481 case QEvent::Leave:
00482 case QEvent::Enter:
00483 QApplication::postEvent(mSpinWidget, new QEvent(e->type()));
00484 QTimer::singleShot(0, this, SLOT(redraw()));
00485 break;
00486 case QEvent::FocusIn:
00487 mSpinbox->setFocus();
00488 QTimer::singleShot(0, this, SLOT(redraw()));
00489 break;
00490 default:
00491 break;
00492 }
00493 return QCanvasView::event(e);
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 static bool mirrorStyle(const QStyle& style)
00506 {
00507 for (const char** s = mirrorStyles; *s; ++s)
00508 if (style.inherits(*s))
00509 return true;
00510 return false;
00511 }