📄 intspinbox.cpp
字号:
frameW = 2; focusSec = 0; setBackgroundMode( PaletteBase ); installEventFilter( this ); setFocusPolicy( WheelFocus );}int Editor::focusSection() const { return focusSec; }void Editor::setFocusSection( int sec ){ focusSec = sec; pmDirty = true;}void Editor::makePixmap(){ if ( pmBuf ) return; QSize s( width() - frameW*2, height() - frameW*2 ); if ( s.width() < 0 ) s.setWidth( 0 ); if ( s.height() < 0 ) s.setHeight( 0 ); pmBuf = new QPixmap( s ); pmDirty = true;}int Editor::xPosToCursorPos( int press_pos ) const{ int x1 = 0; int x2 = 0; int i = 0; QFontMetrics fm = fontMetrics(); QString s = cw->formattedText(); press_pos -= (frameW + 2); while ( i < (int) s.length() ) { x2 = x1 + fm.width( s[i] ); if ( QABS( x1 - press_pos ) < QABS( x2 - press_pos ) ) { return i; } i++; x1 = x2; } return i;}void Editor::resizeEvent( QResizeEvent *re ){ delete pmBuf; pmBuf = 0; QWidget::resizeEvent( re );}void Editor::mousePressEvent( QMouseEvent *me ){ int curpos = xPosToCursorPos( me->pos().x() ); int sec = -1; for ( unsigned int i = 0; i < cw->sectionCount(); ++i ) { if ( curpos >= cw->selStart(i) && curpos <= cw->selEnd(i) ) { sec = i; break; } } if ( sec != -1 ) { if ( cw->setFocusSection( sec ) ) repaint( rect(), false ); }}bool Editor::event( QEvent *ev ){ if ( ev->type() == QEvent::FocusIn || ev->type() == QEvent::FocusOut ) { pmDirty = true; if ( ev->type() == QEvent::FocusOut ) { qApp->sendEvent( cw, ev ); } update( rect() ); } return QWidget::event( ev );}void Editor::updateDisplay(){ pmDirty = true; repaint( rect(), false );}void Editor::paintEvent( QPaintEvent * ){ if ( !pmBuf || pmDirty ) { makePixmap(); if ( pmBuf->isNull() ) { delete pmBuf; pmBuf = 0; return; } QPainter p( pmBuf, this ); const QColorGroup & cg = colorGroup(); // erase previous contents QBrush bg = cg.brush( isEnabled() ? QColorGroup::Base : QColorGroup::Background); p.fillRect( 0, 0, width(), height(), bg ); // draw the text, including the focus section QString txt = cw->formattedText(); int markBegin = cw->selStart( focusSec ); int markEnd = cw->selEnd( focusSec ); QString pre = txt.mid( 0, markBegin ); QString marked = txt.mid( markBegin, markEnd-markBegin ); QString post = txt.mid( markEnd, txt.length() ); QFontMetrics fm = fontMetrics(); int y = (pmBuf->height() + fm.height())/2 - fm.descent() - 1 ; int x = 2; int w = fm.width( pre ); if ( x < pmBuf->width() && x + w >= 0 ) { p.setPen( cg.text() ); p.drawText( x, y, pre ); } x += w; w = fm.width( marked ); if ( x < pmBuf->width() && x + w >= 0 ) { if ( hasFocus() ) { p.fillRect( x, y-fm.ascent()-1, w, fm.height()+2, cg.brush( QColorGroup::Highlight ) ); p.setPen( cg.highlightedText() ); } p.drawText( x, y, marked ); } x += w; w = fm.width( post ); if ( x < pmBuf->width() && x + w >= 0 ) { p.setPen( cg.text() ); p.drawText( x, y, post ); } p.setPen( cg.text() ); pmDirty = false; } QPainter p( this ); p.drawPixmap( frameW, frameW, *pmBuf );}bool Editor::eventFilter( QObject* obj, QEvent* ev ){ if ( obj == this ) { if ( ev->type() == QEvent::KeyPress ) { QKeyEvent *ke = (QKeyEvent*)ev; switch ( ke->key() ) { case Key_Right: if ( focusSec < (int)cw->sectionCount() - 1 ) { if ( cw->setFocusSection( focusSec+1 ) ) repaint( rect(), false ); } return true; case Key_Left: if ( focusSec > 0 ) { if ( cw->setFocusSection( focusSec-1 ) ) repaint( rect(), false ); } return true; case Key_Up: cw->stepUp(); return true; case Key_Down: cw->stepDown(); return true; /*case Key_Backspace: cw->removeFirstNumber( focusSec ); return true; case Key_Delete: cw->removeLastNumber( focusSec ); return true;*/ case Key_Enter: case Key_Return: cw->validate(); return true; case Key_Tab: case Key_BackTab: { if ( ke->state() == Qt::ControlButton ) return false; QWidget* w = this; w = w->parentWidget(); if ( w ) { qApp->sendEvent( w, ev ); return true; } } break; default: QString txt = ke->text().lower(); int num = txt[0].digitValue(); if ( num != -1 ) { cw->addNumber( focusSec, num ); return true; } } } } return false;}/* class IntSpin ------------------------------------------------------- */#define HIDDEN_CHAR '0'IntSpin::~IntSpin(){ sections.setAutoDelete( true ); sections.clear();}IntSpin::IntSpin( QWidget* parent, const char* name ) : QWidget( parent, name, #if (QT_VERSION-0 >= 0x030200) WNoAutoErase )#else // QT_VERSION < 3.2 WResizeNoErase | WRepaintNoErase )#endif{ numSecs = 0; timerId = 0; changed = false; overwrite = true; typing = false; sections.setAutoDelete( false ); ed = new Editor( this, "editor" ); setFocusProxy( ed ); controls = new SpinWidget( this, "controls" ); controls->setEditWidget( ed ); connect( controls, SIGNAL( stepUpPressed() ), this, SLOT( stepUp() ) ); connect( controls, SIGNAL( stepDownPressed() ), this, SLOT( stepDown() ) ); setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) );}void IntSpin::addSection( int min, int max, int curr/*=0*/, int step/*=1*/, QString sep_char/*=" : "*/ ){ sections.append( new NumberSection(numSecs, sep_char) ); sections.at(numSecs)->setValues( min, max, curr, step ); numSecs++;}void IntSpin::setValue( int v, int sec/*=0*/ ){ vk_assert( sec < (int)sections.count() ); sections.at(sec)->setValue( v ); ed->updateDisplay();}void IntSpin::resizeEvent( QResizeEvent * ){ controls->resize( width(), height() ); }QSize IntSpin::minimumSizeHint() const{ return sizeHint(); }/* make the widget exactly the right size such that if all numbers are their maximum values, everything is visible */QSize IntSpin::sizeHint() const{ constPolish(); QFontMetrics fm( font() ); int h = QMAX( fm.lineSpacing(), 14) + 2; h += style().pixelMetric(QStyle::PM_DefaultFrameWidth) * 2; int w = 0; int tw = 0; QString s; QPtrListIterator<NumberSection> it( sections ); NumberSection* aSection; while ( (aSection = it.current()) != 0 ) { ++it; s = QString::number( aSection->minVal() ); w = QMAX( w, fm.width( s ) ); s = QString::number( aSection->maxVal() ); w = QMAX( w, fm.width( s ) ); tw += w; } tw += controls->UpRect().width(); /* when we only have one section, the controls come out smaller, and we need just a bit more width for the number. ho hum. */ if ( sections.count() == 1 ) { tw += fm.width(" "); } return style().sizeFromContents( QStyle::CT_LineEdit, this, QSize(tw,h).expandedTo( QApplication::globalStrut() ));}bool IntSpin::event( QEvent *ev ){ if ( ev->type() == QEvent::FocusOut ) { killTimer( timerId ); validate(); typing = false; if ( changed ) { emit valueChanged( currValueText() ); changed = false; } } return QWidget::event( ev );}QString IntSpin::currValueText(){ QString txt = ""; for ( unsigned int sec = 0; sec < sections.count(); ++sec ) { txt += sectionText( sec ); if ( sec < sections.count()-1 ) txt += ","; } return txt;}QString IntSpin::formattedText(){ int len; int offset = 0; QString txt, tmp; for ( int sec = 0; sec < numSecs; ++sec ) { tmp = sectionText( sec ); len = tmp.length(); /* only pad a single integer if we have > 1 section */ if ( sections.count() > 1 ) { if ( len == 1 ) { tmp = tmp.rightJustify( 2, HIDDEN_CHAR ); len = 2; } } offset += len; setSectionSelection( sec, offset-len, offset ); offset += sections.at(sec)->separator().length(); txt += tmp; if ( sec < numSecs-1 ) { txt += sections.at(sec)->separator(); } } return txt;}void IntSpin::setSectionSelection( int sec, int selstart, int selend ){ if ( sec < 0 || sec > numSecs ) return; sections.at(sec)->setSelectionStart( selstart ); sections.at(sec)->setSelectionEnd( selend );}QString IntSpin::sectionText( int sec ){ sec = sections.at(sec)->index(); QString txt = QString::number( sections.at(sec)->value() ); return txt;}int IntSpin::selStart( int sec ){ return sections.at(sec)->selectionStart(); }int IntSpin::selEnd( int sec ){ return sections.at(sec)->selectionEnd(); }unsigned int IntSpin::sectionCount() { return (unsigned int)numSecs; }bool IntSpin::setFocusSection( int sec ){ if ( sec < 0 || sec > numSecs ) return false; if ( sec != ed->focusSection() ) { killTimer( timerId ); validate(); typing = false; overwrite = true; if ( changed ) { emit valueChanged( currValueText() ); changed = false; } ed->setFocusSection( sec ); return true; } return false;}void IntSpin::stepUp(){ int fsec = ed->focusSection(); int sec = sections.at(fsec)->index(); sections.at(sec)->stepUp(); ed->updateDisplay(); emit valueChanged( currValueText() );}void IntSpin::stepDown(){ int fsec = ed->focusSection(); int sec = sections.at(fsec)->index(); sections.at(sec)->stepDown(); ed->updateDisplay(); emit valueChanged( currValueText() );}void IntSpin::timerEvent( QTimerEvent * ){ validate(); overwrite = true; }/* user might have typed a number. at this point, ed->focusSection() hasn't yet changed. */void IntSpin::validate(){ if ( !typing ) return; int fsec = ed->focusSection(); if ( !sections.at(fsec)->usesPowers() ) return; int temp = tmpBuf.toInt(); if ( sections.at(fsec)->withinRange( temp ) ) { sections.at(fsec)->setValue( temp ); changed = true; ed->updateDisplay(); emit valueChanged( currValueText() ); } tmpBuf = ""; /* clear buffer */ typing = false;}void IntSpin::addNumber( int fsec, int num ){ killTimer( timerId ); typing = true; if ( sections.at(fsec)->usesPowers() ) { tmpBuf += QString::number( num ); } else { bool accepted = false; bool over_write = false; QString txt = sectionText( fsec ); if ( overwrite ) { if ( sections.at(fsec)->withinRange( num ) ) { accepted = true; sections.at(fsec)->setValue( num ); over_write = false; } } else { txt += QString::number( num ); int temp = txt.toInt(); if ( sections.at(fsec)->withinRange( temp ) ) { accepted = true; sections.at(fsec)->setValue( temp ); } } changed = accepted; overwrite = over_write; if ( changed ) { ed->updateDisplay(); emit valueChanged( currValueText() ); } } timerId = startTimer( qApp->doubleClickInterval()*4 );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -