2
* Kivio - Visual Modelling and Flowcharting
3
* Copyright (C) 2000 theKompany.com
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
#include "tkfloatspinbox.h"
20
#include "tktoolbarbutton.h"
26
#include <qpushbutton.h>
29
#include <qlineedit.h>
30
#include <qvalidator.h>
31
#include <qpixmapcache.h>
32
#include <qapplication.h>
35
TKFloatSpinBox::TKFloatSpinBox( QWidget * parent , const char *name )
36
: QFrame( parent, name ), TKFloatRangeControl()
43
TKFloatSpinBox::TKFloatSpinBox( float minValue, float maxValue, float step, int decimal, QWidget* parent, const char* name )
44
: QFrame( parent, name ), TKFloatRangeControl( minValue, maxValue, step, step, minValue )
50
void TKFloatSpinBox::initSpinBox()
52
buttonSymbol = TKFloatSpinBox::UpDownArrows;
60
up = new TKToolBarButton(QPixmap(),QString::null,this,"up");
61
up->setAutoRaised(false);
63
up->setFocusPolicy( QWidget::NoFocus );
64
up->setAutoRepeat( true );
66
down = new TKToolBarButton(QPixmap(),QString::null,this,"down");
67
down->setAutoRaised(false);
68
down->setRaised(true);
69
down->setFocusPolicy( QWidget::NoFocus );
70
down->setAutoRepeat( true );
72
setButtonSymbols(UpDownArrows);
74
validate = new QDoubleValidator( minValue(), maxValue(), m_decimal, this );
75
vi = new QLineEdit(this);
77
vi->setAlignment(AlignRight);
79
setFocusPolicy( StrongFocus );
80
vi->setValidator( validate );
81
vi->installEventFilter( this );
83
setPalettePropagation( AllChildren );
84
setFontPropagation( AllChildren );
86
setSizePolicy( QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ) );
87
setFrameStyle( Panel|Sunken );
90
connect( up, SIGNAL(pressed()), SLOT(stepUp()) );
91
connect( down, SIGNAL(pressed()), SLOT(stepDown()) );
92
connect( vi, SIGNAL(textChanged(const QString&)), SLOT(textChanged()) );
95
TKFloatSpinBox::~TKFloatSpinBox()
99
void TKFloatSpinBox::setDecimals( int decimal )
103
if (validate->inherits("QDoubleValidator"))
104
((QDoubleValidator*)validate)->setDecimals( m_decimal );
109
QString TKFloatSpinBox::text() const
114
QString TKFloatSpinBox::cleanText() const
116
QString s = QString(text()).stripWhiteSpace();
117
if ( !prefix().isEmpty() ) {
118
QString px = QString(prefix()).stripWhiteSpace();
119
int len = px.length();
120
if ( len && s.left(len) == px )
123
if ( !suffix().isEmpty() ) {
124
QString sx = QString(suffix()).stripWhiteSpace();
125
int len = sx.length();
126
if ( len && s.right(len) == sx )
127
s.truncate( s.length() - len );
129
return s.stripWhiteSpace();
132
void TKFloatSpinBox::setPrefix( const QString &text )
138
void TKFloatSpinBox::setSuffix( const QString &text )
144
QString TKFloatSpinBox::prefix() const
146
if ( pfix.isEmpty() )
147
return QString::null;
152
QString TKFloatSpinBox::suffix() const
154
if ( sfix.isEmpty() )
155
return QString::null;
160
void TKFloatSpinBox::setWrapping( bool on )
166
bool TKFloatSpinBox::wrapping() const
171
void TKFloatSpinBox::setFixedLength(int l)
177
QSize TKFloatSpinBox::sizeHint() const
180
QFontMetrics fm = fontMetrics();
181
int fw = frameWidth();
183
int h = m_minimum ? 9 : QMAX(12,fm.height()); // ensure enough space for the button pixmaps
185
// button width - see resizeevent()
190
bw = (height()/2 - fw)*8/5;
192
int w = 35; // minimum width for the value
195
int wl = fm.width('0')*QABS(flength+1);
197
s = prefix() + suffix();
198
w = QMAX( w, fm.width(s) + wl);
200
s = prefix() + ( (TKFloatSpinBox*)this )->mapValueToText( minValue() ) + suffix();
201
w = QMAX(w, fm.width(s));
202
s = prefix() + ( (TKFloatSpinBox*)this )->mapValueToText( maxValue() ) + suffix();
203
w = QMAX(w, fm.width(s));
206
QSize r( bw + fw * 2 // buttons AND frame both sides - see resizeevent()
207
+ 6 // right/left margins
209
fw * 2 // top/bottom frame
210
+ (m_minimum ? 0:4) // top/bottom margins
213
return r.expandedTo( QApplication::globalStrut() );
216
void TKFloatSpinBox::setMinimumStyle(bool minimum)
218
if (m_minimum == minimum)
222
setFrameStyle( m_minimum ? NoFrame:Panel|Sunken );
223
setSizePolicy( QSizePolicy( QSizePolicy::Minimum, m_minimum ? QSizePolicy::Minimum : QSizePolicy::Fixed ) );
228
void TKFloatSpinBox::arrangeWidgets()
233
int fw = frameWidth();
236
bs.setHeight( height() - 2*fw );
239
bs.setHeight( height()/2 - fw );
240
bs.setWidth( bs.height() * 8 / 5 ); // 1.6 - approximate golden mean
243
if ( up->size() != bs || down->size() != bs ) {
246
updateButtonSymbols();
251
int x = width() - fw - 2*bs.width();
253
down->move( x+bs.width(), y );
254
vi->setGeometry( fw, fw, x - fw, height() - 2*fw );
257
int x = width() - fw - bs.width();
259
down->move( x, height() - y - up->height() );
260
vi->setGeometry( fw, fw, x - fw, height() - 2*fw );
264
void TKFloatSpinBox::setValue( float value )
266
directSetValue( value );
270
void TKFloatSpinBox::stepUp()
274
if ( wrapping() && ( value()+lineStep() > maxValue() ) )
275
TKFloatRangeControl::setValue( minValue() );
280
void TKFloatSpinBox::stepDown()
284
if ( wrapping() && ( value()-lineStep() < minValue() ) )
285
TKFloatRangeControl::setValue( maxValue() );
290
bool TKFloatSpinBox::eventFilter( QObject* obj, QEvent* ev )
295
if ( ev->type() == QEvent::FocusOut || ev->type() == QEvent::Leave || ev->type() == QEvent::Hide ) {
298
} else if ( ev->type() == QEvent::KeyPress ) {
299
QKeyEvent* k = (QKeyEvent*)ev;
300
if ( k->key() == Key_Up ) {
303
} else if ( k->key() == Key_Down ) {
306
} else if ( k->key() == Key_Return ) {
314
void TKFloatSpinBox::leaveEvent( QEvent* )
320
void TKFloatSpinBox::resizeEvent( QResizeEvent* )
325
void TKFloatSpinBox::wheelEvent( QWheelEvent* e )
327
kdDebug() << "WHEEL EVENT **************************************\n";
329
static float offset = 0;
330
static TKFloatSpinBox* offset_owner = 0;
331
if (offset_owner != this) {
335
offset += -e->delta()/120;
337
if (QABS(offset) < 1)
341
for (int i=0; i<QABS(ioff); i++)
342
offset > 0 ? stepDown() : stepUp();
347
void TKFloatSpinBox::valueChange()
350
emit valueChanged( value() );
353
void TKFloatSpinBox::rangeChange()
355
if ( validate->inherits( "QDoubleValidator" ) )
356
((QDoubleValidator*)validate)->setRange( minValue(), maxValue() );
360
void TKFloatSpinBox::setValidator( const QValidator* v )
363
vi->setValidator( v );
366
const QValidator * TKFloatSpinBox::validator() const
368
return vi ? vi->validator() : 0;
371
void TKFloatSpinBox::updateDisplay()
373
vi->setText( currentValueText() );
375
up->setEnabled( isEnabled() && (wrapping() || value() < maxValue()) );
376
down->setEnabled( isEnabled() && (wrapping() || value() > minValue()) );
379
void TKFloatSpinBox::interpretText()
382
float newVal = mapTextToValue( &ok );
384
TKFloatRangeControl::setValue( newVal );
389
TKToolBarButton* TKFloatSpinBox::upButton() const
394
TKToolBarButton* TKFloatSpinBox::downButton() const
399
QLineEdit* TKFloatSpinBox::editor() const
404
void TKFloatSpinBox::textChanged()
409
QString TKFloatSpinBox::mapValueToText( float v )
411
QString s = QString::number(v,'f',m_decimal);
415
float TKFloatSpinBox::mapTextToValue( bool* ok )
418
float newVal = s.toDouble( ok );
419
if ( !(*ok) && !( !prefix() && !suffix() ) ) {
421
newVal = s.toDouble( ok );
426
QString TKFloatSpinBox::currentValueText()
430
s.append( mapValueToText( value() ) );
431
s.append( suffix() );
435
void TKFloatSpinBox::setEnabled( bool on )
437
bool b = isEnabled();
438
QFrame::setEnabled( on );
439
if ( isEnabled() != b ) {
444
void TKFloatSpinBox::styleChange( QStyle& old )
446
setFrameStyle( Panel | Sunken );
448
QWidget::styleChange( old );
451
void TKFloatSpinBox::setButtonSymbols( ButtonSymbols newSymbols )
453
if ( buttonSymbols() == newSymbols )
456
buttonSymbol = newSymbols;
457
updateButtonSymbols();
460
TKFloatSpinBox::ButtonSymbols TKFloatSpinBox::buttonSymbols() const
465
void TKFloatSpinBox::updateButtonSymbols()
467
QString key( QString::fromLatin1("$qt$qspinbox$"));
469
bool pmSym = buttonSymbols() == PlusMinus;
471
key += QString::fromLatin1( pmSym ? "+-" : "^v" );
472
key += QString::number( down->height() );
474
QString upKey = key + QString::fromLatin1( "$up" );
475
QString dnKey = key + QString::fromLatin1( "$down" );
480
bool found = QPixmapCache::find( dnKey, dnBm ) && QPixmapCache::find( upKey, upBm );
485
int h = down->height()-4;
490
else if ( (h > 6) && (h & 1) )
493
h -= ( h / 8 ) * 2; // Empty border
496
p.eraseRect( 0, 0, h, h );
497
p.setBrush( color1 );
499
p.drawLine( 0, c, h, c );
501
p.drawLine( 0, c-1, h, c-1 );
506
p.drawLine( c, 0, c, h );
508
p.drawLine( c-1, 0, c-1, h );
511
int w = down->width()-4;
517
w -= ( w / 7 ) * 2; // Empty border
518
int h = w/2 + 2; // Must have empty row at foot of arrow
521
p.eraseRect( 0, 0, w, h );
523
a.setPoints( 3, 0, 1, w-1, 1, h-2, h-1 );
524
p.setBrush( color1 );
529
upBm = dnBm.xForm( wm );
532
QPixmapCache::insert( dnKey, dnBm );
533
QPixmapCache::insert( upKey, upBm );
536
down->setPixmap( dnBm );
537
up->setPixmap( upBm );
540
float TKFloatSpinBox::minValue() const
542
return TKFloatRangeControl::minValue();
545
float TKFloatSpinBox::maxValue() const
547
return TKFloatRangeControl::maxValue();
550
void TKFloatSpinBox::setMinValue( float i )
552
setRange( i, maxValue() );
555
void TKFloatSpinBox::setMaxValue( float i )
557
setRange( minValue(), i );
560
float TKFloatSpinBox::lineStep() const
562
return TKFloatRangeControl::lineStep();
565
void TKFloatSpinBox::setLineStep( float i )
567
setSteps( i, pageStep() );
570
float TKFloatSpinBox::value()
576
return TKFloatRangeControl::value();
579
/*******************************************************************************************/
581
TKFloatRangeControl::TKFloatRangeControl()
590
TKFloatRangeControl::TKFloatRangeControl( float minValue, float maxValue, float lineStep, float pageStep, float value )
594
line = QABS( lineStep );
595
page = QABS( pageStep );
596
val = prevVal = bound( value );
599
void TKFloatRangeControl::setValue(float value)
601
directSetValue( value );
602
if ( prevVal != val )
606
void TKFloatRangeControl::directSetValue(float value)
609
val = bound( value );
612
void TKFloatRangeControl::addPage()
614
if ( value() + pageStep() > value() )
615
setValue( value() + pageStep() );
617
setValue( maxValue() );
620
void TKFloatRangeControl::subtractPage()
622
if ( value() - pageStep() < value() )
623
setValue( value() - pageStep() );
625
setValue( minValue() );
628
void TKFloatRangeControl::addLine()
630
setValue( value() + lineStep() );
633
void TKFloatRangeControl::subtractLine()
635
setValue( value() - lineStep() );
638
void TKFloatRangeControl::setRange(float minValue, float maxValue)
640
if ( minValue == minVal && maxValue == maxVal )
642
if ( minValue > maxValue ) {
643
minVal = maxVal = minValue;
648
float tmp = bound( val );
657
void TKFloatRangeControl::setSteps(float lineStep,float pageStep)
659
if (lineStep != line || pageStep != page) {
660
line = QABS(lineStep);
661
page = QABS(pageStep);
666
void TKFloatRangeControl::valueChange()
670
void TKFloatRangeControl::rangeChange()
674
void TKFloatRangeControl::stepChange()
678
float TKFloatRangeControl::bound(float v) const
680
if ( v - minVal < 1.0e-05 )
686
/***************************************************************************************/
687
TKUFloatSpinBox::TKUFloatSpinBox( QWidget* parent, const char* name)
688
: TKFloatSpinBox(parent,name)
691
setUnit((int)UnitPoint);
694
TKUFloatSpinBox::TKUFloatSpinBox( float minValue, float maxValue, float step, int decimal, QWidget* parent, const char* name)
695
: TKFloatSpinBox(minValue,maxValue,step,decimal,parent,name)
697
setUnit((int)UnitPoint);
700
TKUFloatSpinBox::~TKUFloatSpinBox()
704
void TKUFloatSpinBox::setUnit(int unit)
707
setSuffix(hideSuffix ? QString::null : unitToString(unit));
708
float v = cvtPtToUnit(unit,cvtUnitToPt(m_unit,TKFloatSpinBox::value()));
709
setMinValue( cvtPtToUnit(unit,cvtUnitToPt(m_unit,minValue())) );
710
setMaxValue( cvtPtToUnit(unit,cvtUnitToPt(m_unit,maxValue())) );
711
TKFloatSpinBox::setValue( v );
717
float TKUFloatSpinBox::value(int unit)
719
return cvtPtToUnit(unit,cvtUnitToPt(m_unit,TKFloatSpinBox::value()));
722
void TKUFloatSpinBox::setValue(float value,int unit)
724
TKFloatSpinBox::setValue( cvtPtToUnit(m_unit,cvtUnitToPt(unit,value)) );
727
void TKUFloatSpinBox::setHideSuffix(bool f)
733
setSuffix(hideSuffix ? QString::null : unitToString(m_unit));
737
#include "tkfloatspinbox.moc"