rendered paste body
#include <QHBoxLayout>
#include <QSpinBox>
#include <QLabel>
#include <QObject>
#include <cmath>
#include "latlonbox.h"
LatLonBox::LatLonBox(QWidget *parent) : QWidget( parent ),
m_layout(0),
m_degreesSpin(0),
m_minutesSpin(0),
m_secondsSpin(0),
m_degreesLabel(0),
m_minutesLabel(0),
m_secondsLabel(0)
{
m_value = 0;
m_layout = new QHBoxLayout;
setLayout( m_layout );
m_degreesSpin = new QSpinBox;
m_degreesSpin->setMinimum( -180 );
m_degreesSpin->setMaximum( 180 );
m_degreesSpin->show();
m_minutesSpin = new QSpinBox;
//minimum value is -1 so we can
//reduce the next one over
m_minutesSpin->setMinimum( -1 );
m_minutesSpin->setMaximum( 60 );
m_minutesSpin->show();
m_secondsSpin = new QSpinBox;
m_secondsSpin->setMinimum( -1 );
m_secondsSpin->setMaximum( 60 );
m_secondsSpin->show();
m_degreesLabel = new QLabel( QString::fromUtf8("\u00b0") );
m_minutesLabel = new QLabel( QString("\'") );
m_secondsLabel = new QLabel( QString("\"") );
m_layout->addWidget( m_degreesSpin );
m_layout->addWidget( m_degreesLabel );
m_layout->addWidget( m_minutesSpin );
m_layout->addWidget( m_minutesLabel );
m_layout->addWidget( m_secondsSpin );
m_layout->addWidget( m_secondsLabel );
connect( m_secondsSpin, SIGNAL( valueChanged( int ) ),
this, SLOT( secondsOverflow( ) ) );
connect( m_minutesSpin, SIGNAL( valueChanged( int ) ),
this, SLOT( minutesOverflow( ) ) );
connect( m_degreesSpin, SIGNAL( valueChanged( int ) ),
this, SLOT( recalculate( ) ) );
}
void LatLonBox::secondsOverflow()
{
if( m_secondsSpin->value() == 60 ) {
m_secondsSpin->setValue( 0 );
m_minutesSpin->setValue( m_minutesSpin->value() + 1 );
recalculate();
return;
} else if( m_secondsSpin->value() == -1 ) {
m_secondsSpin->setValue( 59 );
m_minutesSpin->setValue( m_minutesSpin->value() - 1 );
recalculate();
return;
}
}
void LatLonBox::minutesOverflow()
{
if( m_minutesSpin->value() == 60 ) {
m_minutesSpin->setValue( 0 );
m_degreesSpin->setValue( m_degreesSpin->value() + 1 );
recalculate();
return;
} else if( m_minutesSpin->value() == -1 ) {
m_minutesSpin->setValue( 59 );
m_degreesSpin->setValue( m_degreesSpin->value() - 1 );
recalculate();
return;
}
}
void LatLonBox::setValue( double newvalue )
{
m_value = newvalue;
reverseRecalculate();
}
void LatLonBox::recalculate()
{
//we need two because if the degrees is neg,
//the mins/secs *subtract* from the value
if( m_degreesSpin->value() >= 0 ) {
double newvalue = m_degreesSpin->value();
newvalue += m_minutesSpin->value() / 60;
newvalue += m_secondsSpin->value() / 3600;
if( newvalue != m_value ) {
m_value = newvalue;
emit valueChanged( m_value );
}
} else {
double newvalue = m_degreesSpin->value();
newvalue -= m_minutesSpin->value() / 60;
newvalue -= m_secondsSpin->value() / 3600;
if( newvalue != m_value ) {
m_value = newvalue;
emit valueChanged( m_value );
}
}
//you can't have 180*59'59" , only 180.
if( m_degreesSpin->value() == 180 ||
m_degreesSpin->value() == -180 ) {
m_minutesSpin->setValue( 0 );
m_secondsSpin->setValue( 0 );
}
}
void LatLonBox::reverseRecalculate()
{
int degreesvalue = 0;
int minutesvalue = 0;
int secondsvalue = 0;
if( m_value >= 0 ) {
//degreesvalue is the whole degree part
degreesvalue = floor( m_value );
//minutesremainder is the fraction of a degree that
//is left over
double minutesremainder = m_value - degreesvalue;
//multipy the fraction of a degree by 60 to
//turn it into minutes
minutesremainder = minutesremainder * 60;
//minutesvalue is the whole minutes part
minutesvalue = floor( minutesremainder );
//secondsremainder is the fraction of a minute
//that is left over
double secondsremainder = minutesremainder - minutesvalue;
//multiply the fraction of a minute by 60 to
//turn it into seconds
secondsvalue = secondsremainder * 60;
//now we have all the values, we
//put them on the boxes.
m_degreesSpin->setValue( degreesvalue );
m_minutesSpin->setValue( minutesvalue );
m_secondsSpin->setValue( secondsvalue );
} else {
degreesvalue = ceil( m_value );
double minutesremainder = m_value - degreesvalue;
minutesremainder = minutesremainder * 60;
minutesvalue = ceil( minutesremainder );
double secondsremainder = minutesremainder - minutesvalue;
secondsvalue = secondsremainder * 60;
m_degreesSpin->setValue( degreesvalue );
m_minutesSpin->setValue( minutesvalue );
m_secondsSpin->setValue( secondsvalue );
}
}