00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "cnitem.h"
00012 #include "doublespinbox.h"
00013
00014 #include <kdebug.h>
00015 #include <kglobal.h>
00016 #include <klocale.h>
00017
00018 #include <qlineedit.h>
00019 #include <qregexp.h>
00020 #include <qtimer.h>
00021
00022 #include <algorithm>
00023 #include <cmath>
00024 using namespace std;
00025
00026
00027 inline int roundDouble( double val )
00028 {
00029 return (val > 0) ? int(val+0.5) : int(val-0.5);
00030 }
00031
00032
00033 DoubleSpinBox::DoubleSpinBox( double lower, double upper, double minAbs, double value, const QString &unit, QWidget * parent )
00034 : QSpinBox( parent )
00035 {
00036 m_lastEmittedValue = value;
00037 m_unit = unit;
00038 m_minValue = lower;
00039 m_maxValue = upper;
00040 m_minAbsValue = minAbs;
00041 m_queuedSuffix = QString::null;
00042
00043 editor()->setAlignment( Qt::AlignRight );
00044
00045 connect( this, SIGNAL(valueChanged(int)), this, SLOT(checkIfChanged()) );
00046 QSpinBox::setMinValue( -(1<<30) );
00047 QSpinBox::setMaxValue( +(1<<30) );
00048 setValue( value );
00049
00050 setValidator( 0 );
00051 }
00052
00053
00054 DoubleSpinBox::~DoubleSpinBox()
00055 {
00056 }
00057
00058
00059 double DoubleSpinBox::value()
00060 {
00061 return getDisplayedNumber( 0 ) * getMult();
00062 }
00063
00064
00065 void DoubleSpinBox::setValue( double value )
00066 {
00067 if ( value > maxValue() )
00068 value = maxValue();
00069
00070 else if ( value < minValue() )
00071 value = minValue();
00072
00073 if ( std::abs(value) < m_minAbsValue*0.9999 )
00074 value = 0.0;
00075
00076 updateSuffix( value );
00077
00078 QSpinBox::setValue( roundDouble( (value / Item::getMultiplier( value )) * 100 ) );
00079 }
00080
00081
00082 void DoubleSpinBox::setUnit( const QString & unit )
00083 {
00084 updateSuffix( value() );
00085 m_unit = unit;
00086 }
00087
00088
00089 void DoubleSpinBox::updateSuffix( double value )
00090 {
00091 m_queuedSuffix = " " + CNItem::getNumberMag( value ) + m_unit;
00092
00093
00094 if ( m_queuedSuffix.stripWhiteSpace().isEmpty() )
00095 m_queuedSuffix = "";
00096
00097 QTimer::singleShot( 0, this, SLOT(setQueuedSuffix()) );
00098 }
00099
00100
00101 void DoubleSpinBox::setQueuedSuffix()
00102 {
00103 bool changed = false;
00104 if ( !m_queuedSuffix.isNull() && suffix() != m_queuedSuffix )
00105 {
00106 setSuffix( m_queuedSuffix );
00107 changed = true;
00108 }
00109 m_queuedSuffix = QString::null;
00110
00111 if ( changed )
00112 emit valueChanged( value() );
00113 }
00114
00115
00116 double DoubleSpinBox::getMult()
00117 {
00118 QString text = this->text().stripWhiteSpace();
00119 if ( !m_queuedSuffix.isNull() )
00120 {
00121 QString nsSuffix = suffix().stripWhiteSpace();
00122
00123 if ( nsSuffix.isEmpty() )
00124 text.append( m_queuedSuffix );
00125 else
00126 text.replace( nsSuffix, m_queuedSuffix );
00127 }
00128
00129 if ( text.length() == 0 )
00130 return 1.0;
00131
00132 if ( text.endsWith( m_unit, false ) )
00133 text = text.remove( text.length() - m_unit.length(), m_unit.length() );
00134
00135 text.stripWhiteSpace();
00136
00137 QChar siExp = text[ text.length()-1 ];
00138
00139 if ( siExp.isLetter() || siExp.isSymbol() )
00140 return CNItem::getMultiplier((QString)siExp);
00141
00142 else
00143 return 1;
00144 }
00145
00146
00147 double DoubleSpinBox::getDisplayedNumber( bool * ok )
00148 {
00149 KLocale * locale = KGlobal::locale();
00150
00151
00152 const QString exclude = locale->decimalSymbol()
00153 + locale->thousandsSeparator()
00154 + locale->positiveSign()
00155 + locale->negativeSign();
00156
00157 QString number = cleanText().remove( QRegExp("[^"+exclude+"\\d]") );
00158
00159 return locale->readNumber( number, ok );
00160 }
00161
00162
00163 int DoubleSpinBox::mapTextToValue( bool * ok )
00164 {
00165 (void)ok;
00166
00167 double value = this->value();
00168
00169 if ( value > maxValue() )
00170 value = maxValue();
00171
00172 else if ( value < minValue() )
00173 value = minValue();
00174
00175 if ( std::abs(value) < m_minAbsValue*0.9999 )
00176 value = 0.0;
00177
00178 updateSuffix( value );
00179
00180 value /= Item::getMultiplier( value );
00181
00182
00183 return int( value * 100 );
00184 }
00185
00186
00187 QString DoubleSpinBox::mapValueToText( int v )
00188 {
00189 double val = double(v)/100.0;
00190
00191 int leftDigits = (int)floor( log10( abs(val) ) ) + 1;
00192 if ( leftDigits < 0 )
00193 leftDigits = 0;
00194 else if ( leftDigits > 3 )
00195 leftDigits = 3;
00196
00197 KLocale * locale = KGlobal::locale();
00198 return locale->formatNumber( val, 3-leftDigits );
00199 }
00200
00201
00202 void DoubleSpinBox::checkIfChanged()
00203 {
00204 double newValue = value();
00205
00206 if ( m_lastEmittedValue == newValue )
00207 return;
00208
00209 m_lastEmittedValue = newValue;
00210 emit valueChanged( m_lastEmittedValue );
00211 }
00212
00213
00214 double DoubleSpinBox::roundToOneSF( double value )
00215 {
00216 if ( value == 0.0 )
00217 return 0.0;
00218
00219 value *= 1.000001;
00220 double tens = pow( 10.0, floor(log10( abs(value) )) );
00221
00222 return int ( value / tens ) * tens;
00223 }
00224
00225
00226 void DoubleSpinBox::stepUp()
00227 {
00228 double value = roundToOneSF( this->value() );
00229
00230 if ( value == 0 )
00231 value = m_minAbsValue;
00232
00233 else if ( value > 0 )
00234 value += std::pow( 10., std::floor( std::log10(value) ) );
00235
00236 else
00237 {
00238 double sub = std::pow(10., std::floor( std::log10(std::abs(value))-1) );
00239 value += std::pow( 10., std::floor( std::log10(std::abs(value)-sub) ) );
00240 }
00241
00242 value *= 1.00001;
00243
00244 if ( std::abs(value) < m_minAbsValue )
00245 value = 0.;
00246
00247 setValue( value );
00248 }
00249
00250
00251 void DoubleSpinBox::stepDown()
00252 {
00253 double value = roundToOneSF( this->value() );
00254
00255 if ( value == 0 )
00256 value = -m_minAbsValue;
00257
00258 else if ( value > 0 )
00259 {
00260 double sub = std::pow(10., std::floor( std::log10(value)-1) );
00261 value -= std::pow( 10., std::floor( std::log10(value-sub) ) );
00262 }
00263 else
00264 {
00265 double add = std::pow(10., std::floor( std::log10(std::abs(value))-1) );
00266 value -= std::pow( 10., std::floor( std::log10(std::abs(value)+add) ) );
00267 }
00268
00269 value *= 1.00001;
00270
00271 if ( std::abs(value) < m_minAbsValue )
00272 value = 0.;
00273
00274 setValue( value );
00275 }
00276
00277 #include "doublespinbox.moc"
00278