Skip to content
qwt_analog_clock.cpp 5.71 KiB
Newer Older
pixhawk's avatar
pixhawk committed
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 * Qwt Widget Library
 * Copyright (C) 1997   Josef Wilgen
 * Copyright (C) 2002   Uwe Rathmann
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the Qwt License, Version 1.0
 *****************************************************************************/

#include "qwt_analog_clock.h"
Bryant's avatar
Bryant committed
#include "qwt_round_scale_draw.h"
#include <qmath.h>
#include <qlocale.h>
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
class QwtAnalogClockScaleDraw: public QwtRoundScaleDraw
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
public:
    QwtAnalogClockScaleDraw()
    {
        setSpacing( 8 );

        enableComponent( QwtAbstractScaleDraw::Backbone, false );

        setTickLength( QwtScaleDiv::MinorTick, 2 );
        setTickLength( QwtScaleDiv::MediumTick, 4 );
        setTickLength( QwtScaleDiv::MajorTick, 8 );

        setPenWidth( 1 );
    }

    virtual QwtText label( double value ) const
    {
        if ( qFuzzyCompare( value + 1.0, 1.0 ) )
            value = 60.0 * 60.0 * 12.0;

        return QLocale().toString( qRound( value / ( 60.0 * 60.0 ) ) );
    }
};
pixhawk's avatar
pixhawk committed

/*!
  Constructor
  \param parent Parent widget
*/
Bryant's avatar
Bryant committed
QwtAnalogClock::QwtAnalogClock( QWidget *parent ):
    QwtDial( parent )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    setWrapping( true );
    setReadOnly( true );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    setOrigin( 270.0 );
    setScaleDraw( new QwtAnalogClockScaleDraw() );

    setTotalSteps( 60 );

    const int secondsPerHour = 60.0 * 60.0; 
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    QList<double> majorTicks;
    QList<double> minorTicks;
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
    for ( int i = 0; i < 12; i++ )
    {
        majorTicks += i * secondsPerHour;
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
        for ( int j = 1; j < 5; j++ )
            minorTicks += i * secondsPerHour + j * secondsPerHour / 5.0;
    }

    QwtScaleDiv scaleDiv;
    scaleDiv.setInterval( 0.0, 12.0 * secondsPerHour );
    scaleDiv.setTicks( QwtScaleDiv::MajorTick, majorTicks );
    scaleDiv.setTicks( QwtScaleDiv::MinorTick, minorTicks );
    setScale( scaleDiv );

    QColor knobColor = palette().color( QPalette::Active, QPalette::Text );
    knobColor = knobColor.dark( 120 );
pixhawk's avatar
pixhawk committed

    QColor handColor;
    int width;

Bryant's avatar
Bryant committed
    for ( int i = 0; i < NHands; i++ )
    {
        if ( i == SecondHand )
        {
pixhawk's avatar
pixhawk committed
            width = 2;
Bryant's avatar
Bryant committed
            handColor = knobColor.dark( 120 );
        }
        else
        {
pixhawk's avatar
pixhawk committed
            width = 8;
            handColor = knobColor;
        }

        QwtDialSimpleNeedle *hand = new QwtDialSimpleNeedle(
Bryant's avatar
Bryant committed
            QwtDialSimpleNeedle::Arrow, true, handColor, knobColor );
        hand->setWidth( width );
pixhawk's avatar
pixhawk committed

        d_hand[i] = NULL;
Bryant's avatar
Bryant committed
        setHand( static_cast<Hand>( i ), hand );
pixhawk's avatar
pixhawk committed
    }
}

//! Destructor
QwtAnalogClock::~QwtAnalogClock()
{
    for ( int i = 0; i < NHands; i++ )
        delete d_hand[i];
}

Bryant's avatar
Bryant committed
  Nop method, use setHand() instead
  \sa setHand()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtAnalogClock::setNeedle( QwtDialNeedle * )
pixhawk's avatar
pixhawk committed
{
    // no op
    return;
}

/*!
Bryant's avatar
Bryant committed
   Set a clock hand
pixhawk's avatar
pixhawk committed
   \param hand Specifies the type of hand
   \param needle Hand
Bryant's avatar
Bryant committed
   \sa hand()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtAnalogClock::setHand( Hand hand, QwtDialNeedle *needle )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( hand >= 0 && hand < NHands )
    {
pixhawk's avatar
pixhawk committed
        delete d_hand[hand];
        d_hand[hand] = needle;
    }
}

/*!
  \return Clock hand
  \param hd Specifies the type of hand
Bryant's avatar
Bryant committed
  \sa setHand()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
QwtDialNeedle *QwtAnalogClock::hand( Hand hd )
pixhawk's avatar
pixhawk committed
{
    if ( hd < 0 || hd >= NHands )
        return NULL;

    return d_hand[hd];
}

/*!
  \return Clock hand
  \param hd Specifies the type of hand
Bryant's avatar
Bryant committed
  \sa setHand()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
const QwtDialNeedle *QwtAnalogClock::hand( Hand hd ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    return const_cast<QwtAnalogClock *>( this )->hand( hd );
pixhawk's avatar
pixhawk committed
}

/*!
  \brief Set the current time
*/
void QwtAnalogClock::setCurrentTime()
Bryant's avatar
Bryant committed
    setTime( QTime::currentTime() );
pixhawk's avatar
pixhawk committed
}

/*!
pixhawk's avatar
pixhawk committed
  \param time Time to display
*/
Bryant's avatar
Bryant committed
void QwtAnalogClock::setTime( const QTime &time )
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    if ( time.isValid() )
    {
        setValue( ( time.hour() % 12 ) * 60.0 * 60.0
            + time.minute() * 60.0 + time.second() );
    }
    else
        setValid( false );
pixhawk's avatar
pixhawk committed
}

/*!
  \brief Draw the needle

Bryant's avatar
Bryant committed
  A clock has no single needle but three hands instead. drawNeedle()
pixhawk's avatar
pixhawk committed
  translates value() into directions for the hands and calls
  drawHand().

  \param painter Painter
  \param center Center of the clock
  \param radius Maximum length for the hands
Bryant's avatar
Bryant committed
  \param dir Dummy, not used.
  \param colorGroup ColorGroup
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
  \sa drawHand()
pixhawk's avatar
pixhawk committed
*/
Bryant's avatar
Bryant committed
void QwtAnalogClock::drawNeedle( QPainter *painter, const QPointF &center,
    double radius, double dir, QPalette::ColorGroup colorGroup ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    Q_UNUSED( dir );

    if ( isValid() )
    {
        const double hours = value() / ( 60.0 * 60.0 );
        const double minutes = 
            ( value() - qFloor(hours) * 60.0 * 60.0 ) / 60.0;
        const double seconds = value() - qFloor(hours) * 60.0 * 60.0
            - qFloor(minutes) * 60.0;

        double angle[NHands];
        angle[HourHand] = 360.0 * hours / 12.0;
        angle[MinuteHand] = 360.0 * minutes / 60.0;
        angle[SecondHand] = 360.0 * seconds / 60.0;

        for ( int hand = 0; hand < NHands; hand++ )
        {
            const double d = 360.0 - angle[hand] - origin();
            drawHand( painter, static_cast<Hand>( hand ), 
                center, radius, d, colorGroup );
        }
pixhawk's avatar
pixhawk committed
    }
}

/*!
  Draw a clock hand

  \param painter Painter
  \param hd Specify the type of hand
  \param center Center of the clock
  \param radius Maximum length for the hands
  \param direction Direction of the hand in degrees, counter clockwise
  \param cg ColorGroup
*/
Bryant's avatar
Bryant committed
void QwtAnalogClock::drawHand( QPainter *painter, Hand hd,
    const QPointF &center, double radius, double direction,
    QPalette::ColorGroup cg ) const
pixhawk's avatar
pixhawk committed
{
Bryant's avatar
Bryant committed
    const QwtDialNeedle *needle = hand( hd );
    if ( needle )
    {
pixhawk's avatar
pixhawk committed
        if ( hd == HourHand )
Bryant's avatar
Bryant committed
            radius = qRound( 0.8 * radius );
pixhawk's avatar
pixhawk committed

Bryant's avatar
Bryant committed
        needle->draw( painter, center, radius, direction, cg );
pixhawk's avatar
pixhawk committed
    }
}