All pastes #962879 Raw Edit

Untitled

public text v1 · immutable
#962879 ·published 2008-03-30 02:06 UTC
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 );
        }
}