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