|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2003-2004 by David Saxton *
|
|
|
|
* david@bluehaze.org *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "cnitem.h"
|
|
|
|
#include "doublespinbox.h"
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tdeglobal.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
|
|
|
|
#include <tqlineedit.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cmath>
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
|
|
inline int roundDouble( double val )
|
|
|
|
{
|
|
|
|
return (val > 0) ? int(val+0.5) : int(val-0.5);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DoubleSpinBox::DoubleSpinBox( double lower, double upper, double minAbs, double value, const TQString &unit, TQWidget * parent )
|
|
|
|
: TQSpinBox( parent )
|
|
|
|
{
|
|
|
|
m_lastEmittedValue = value;
|
|
|
|
m_unit = unit;
|
|
|
|
m_minValue = lower;
|
|
|
|
m_maxValue = upper;
|
|
|
|
m_minAbsValue = minAbs;
|
|
|
|
m_queuedSuffix = TQString();
|
|
|
|
|
|
|
|
editor()->setAlignment( TQt::AlignRight );
|
|
|
|
|
|
|
|
connect( this, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(checkIfChanged()) );
|
|
|
|
TQSpinBox::setMinValue( -(1<<30) );
|
|
|
|
TQSpinBox::setMaxValue( +(1<<30) );
|
|
|
|
setValue( value );
|
|
|
|
|
|
|
|
setValidator( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DoubleSpinBox::~DoubleSpinBox()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double DoubleSpinBox::value()
|
|
|
|
{
|
|
|
|
return getDisplayedNumber( 0 ) * getMult();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DoubleSpinBox::setValue( double value )
|
|
|
|
{
|
|
|
|
if ( value > maxValue() )
|
|
|
|
value = maxValue();
|
|
|
|
|
|
|
|
else if ( value < minValue() )
|
|
|
|
value = minValue();
|
|
|
|
|
|
|
|
if ( std::abs(value) < m_minAbsValue*0.9999 )
|
|
|
|
value = 0.0;
|
|
|
|
|
|
|
|
updateSuffix( value );
|
|
|
|
|
|
|
|
TQSpinBox::setValue( roundDouble( (value / Item::getMultiplier( value )) * 100 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DoubleSpinBox::setUnit( const TQString & unit )
|
|
|
|
{
|
|
|
|
updateSuffix( value() );
|
|
|
|
m_unit = unit;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DoubleSpinBox::updateSuffix( double value )
|
|
|
|
{
|
|
|
|
m_queuedSuffix = " " + CNItem::getNumberMag( value ) + m_unit;
|
|
|
|
|
|
|
|
// Set suffix to be empty if it is nothing but white space
|
|
|
|
if ( m_queuedSuffix.stripWhiteSpace().isEmpty() )
|
|
|
|
m_queuedSuffix = "";
|
|
|
|
|
|
|
|
TQTimer::singleShot( 0, this, TQT_SLOT(setQueuedSuffix()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DoubleSpinBox::setQueuedSuffix()
|
|
|
|
{
|
|
|
|
bool changed = false;
|
|
|
|
if ( !m_queuedSuffix.isNull() && suffix() != m_queuedSuffix )
|
|
|
|
{
|
|
|
|
setSuffix( m_queuedSuffix );
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
m_queuedSuffix = TQString();
|
|
|
|
|
|
|
|
if ( changed )
|
|
|
|
emit valueChanged( value() );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double DoubleSpinBox::getMult()
|
|
|
|
{
|
|
|
|
TQString text = this->text().stripWhiteSpace();
|
|
|
|
if ( !m_queuedSuffix.isNull() )
|
|
|
|
{
|
|
|
|
TQString nsSuffix = suffix().stripWhiteSpace();
|
|
|
|
|
|
|
|
if ( nsSuffix.isEmpty() )
|
|
|
|
text.append( m_queuedSuffix );
|
|
|
|
else
|
|
|
|
text.replace( nsSuffix, m_queuedSuffix );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( text.length() == 0 )
|
|
|
|
return 1.0;
|
|
|
|
|
|
|
|
if ( text.endsWith( m_unit, false ) )
|
|
|
|
text = text.remove( text.length() - m_unit.length(), m_unit.length() );
|
|
|
|
|
|
|
|
text.stripWhiteSpace();
|
|
|
|
|
|
|
|
TQChar siExp = text[ text.length()-1 ];
|
|
|
|
|
|
|
|
if ( siExp.isLetter() || siExp.isSymbol() )
|
|
|
|
return CNItem::getMultiplier((TQString)siExp);
|
|
|
|
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double DoubleSpinBox::getDisplayedNumber( bool * ok )
|
|
|
|
{
|
|
|
|
TDELocale * locale = TDEGlobal::locale();
|
|
|
|
|
|
|
|
// Fetch the characters that we don't want to discard
|
|
|
|
const TQString exclude = locale->decimalSymbol()
|
|
|
|
+ locale->thousandsSeparator()
|
|
|
|
+ locale->positiveSign()
|
|
|
|
+ locale->negativeSign();
|
|
|
|
|
|
|
|
TQString number = cleanText().remove( TQRegExp("[^"+exclude+"\\d]") );
|
|
|
|
|
|
|
|
return locale->readNumber( number, ok );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int DoubleSpinBox::mapTextToValue( bool * ok )
|
|
|
|
{
|
|
|
|
(void)ok;
|
|
|
|
|
|
|
|
double value = this->value();
|
|
|
|
|
|
|
|
if ( value > maxValue() )
|
|
|
|
value = maxValue();
|
|
|
|
|
|
|
|
else if ( value < minValue() )
|
|
|
|
value = minValue();
|
|
|
|
|
|
|
|
if ( std::abs(value) < m_minAbsValue*0.9999 )
|
|
|
|
value = 0.0;
|
|
|
|
|
|
|
|
updateSuffix( value );
|
|
|
|
|
|
|
|
value /= Item::getMultiplier( value );
|
|
|
|
|
|
|
|
// Precision of 2 extra digits
|
|
|
|
return int( value * 100 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString DoubleSpinBox::mapValueToText( int v )
|
|
|
|
{
|
|
|
|
double val = double(v)/100.0;
|
|
|
|
|
|
|
|
int leftDigits = (int)floor( log10( abs(val) ) ) + 1;
|
|
|
|
if ( leftDigits < 0 )
|
|
|
|
leftDigits = 0;
|
|
|
|
else if ( leftDigits > 3 )
|
|
|
|
leftDigits = 3;
|
|
|
|
|
|
|
|
TDELocale * locale = TDEGlobal::locale();
|
|
|
|
return locale->formatNumber( val, 3-leftDigits );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DoubleSpinBox::checkIfChanged()
|
|
|
|
{
|
|
|
|
double newValue = value();
|
|
|
|
|
|
|
|
if ( m_lastEmittedValue == newValue )
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_lastEmittedValue = newValue;
|
|
|
|
emit valueChanged( m_lastEmittedValue );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double DoubleSpinBox::roundToOneSF( double value )
|
|
|
|
{
|
|
|
|
if ( value == 0.0 )
|
|
|
|
return 0.0;
|
|
|
|
|
|
|
|
value *= 1.000001;
|
|
|
|
double tens = pow( 10.0, floor(log10( abs(value) )) );
|
|
|
|
|
|
|
|
return int ( value / tens ) * tens;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DoubleSpinBox::stepUp()
|
|
|
|
{
|
|
|
|
double value = roundToOneSF( this->value() );
|
|
|
|
|
|
|
|
if ( value == 0 )
|
|
|
|
value = m_minAbsValue;
|
|
|
|
|
|
|
|
else if ( value > 0 )
|
|
|
|
value += std::pow( 10., std::floor( std::log10(value) ) );
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double sub = std::pow(10., std::floor( std::log10(std::abs(value))-1) );
|
|
|
|
value += std::pow( 10., std::floor( std::log10(std::abs(value)-sub) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
value *= 1.00001;
|
|
|
|
|
|
|
|
if ( std::abs(value) < m_minAbsValue )
|
|
|
|
value = 0.;
|
|
|
|
|
|
|
|
setValue( value );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DoubleSpinBox::stepDown()
|
|
|
|
{
|
|
|
|
double value = roundToOneSF( this->value() );
|
|
|
|
|
|
|
|
if ( value == 0 )
|
|
|
|
value = -m_minAbsValue;
|
|
|
|
|
|
|
|
else if ( value > 0 )
|
|
|
|
{
|
|
|
|
double sub = std::pow(10., std::floor( std::log10(value)-1) );
|
|
|
|
value -= std::pow( 10., std::floor( std::log10(value-sub) ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double add = std::pow(10., std::floor( std::log10(std::abs(value))-1) );
|
|
|
|
value -= std::pow( 10., std::floor( std::log10(std::abs(value)+add) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
value *= 1.00001;
|
|
|
|
|
|
|
|
if ( std::abs(value) < m_minAbsValue )
|
|
|
|
value = 0.;
|
|
|
|
|
|
|
|
setValue( value );
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "doublespinbox.moc"
|
|
|
|
|