qwt_analog_clock.cpp 5.71 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9 10
/* -*- 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
11 12 13
#include "qwt_round_scale_draw.h"
#include <qmath.h>
#include <qlocale.h>
pixhawk's avatar
pixhawk committed
14

Bryant's avatar
Bryant committed
15
class QwtAnalogClockScaleDraw: public QwtRoundScaleDraw
pixhawk's avatar
pixhawk committed
16
{
Bryant's avatar
Bryant committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
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
39 40 41 42 43

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

Bryant's avatar
Bryant committed
50 51 52 53 54 55
    setOrigin( 270.0 );
    setScaleDraw( new QwtAnalogClockScaleDraw() );

    setTotalSteps( 60 );

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

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

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

Bryant's avatar
Bryant committed
64 65 66 67 68 69 70 71 72 73 74 75
        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
76 77 78 79

    QColor handColor;
    int width;

Bryant's avatar
Bryant committed
80 81 82 83
    for ( int i = 0; i < NHands; i++ )
    {
        if ( i == SecondHand )
        {
pixhawk's avatar
pixhawk committed
84
            width = 2;
Bryant's avatar
Bryant committed
85 86 87 88
            handColor = knobColor.dark( 120 );
        }
        else
        {
pixhawk's avatar
pixhawk committed
89 90 91 92 93
            width = 8;
            handColor = knobColor;
        }

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

        d_hand[i] = NULL;
Bryant's avatar
Bryant committed
98
        setHand( static_cast<Hand>( i ), hand );
pixhawk's avatar
pixhawk committed
99 100 101 102 103 104 105 106 107 108
    }
}

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

109
/*!
Bryant's avatar
Bryant committed
110 111
  Nop method, use setHand() instead
  \sa setHand()
pixhawk's avatar
pixhawk committed
112
*/
Bryant's avatar
Bryant committed
113
void QwtAnalogClock::setNeedle( QwtDialNeedle * )
pixhawk's avatar
pixhawk committed
114 115 116 117 118 119
{
    // no op
    return;
}

/*!
Bryant's avatar
Bryant committed
120
   Set a clock hand
pixhawk's avatar
pixhawk committed
121 122
   \param hand Specifies the type of hand
   \param needle Hand
Bryant's avatar
Bryant committed
123
   \sa hand()
pixhawk's avatar
pixhawk committed
124
*/
Bryant's avatar
Bryant committed
125
void QwtAnalogClock::setHand( Hand hand, QwtDialNeedle *needle )
pixhawk's avatar
pixhawk committed
126
{
Bryant's avatar
Bryant committed
127 128
    if ( hand >= 0 && hand < NHands )
    {
pixhawk's avatar
pixhawk committed
129 130 131 132 133 134 135 136
        delete d_hand[hand];
        d_hand[hand] = needle;
    }
}

/*!
  \return Clock hand
  \param hd Specifies the type of hand
Bryant's avatar
Bryant committed
137
  \sa setHand()
pixhawk's avatar
pixhawk committed
138
*/
Bryant's avatar
Bryant committed
139
QwtDialNeedle *QwtAnalogClock::hand( Hand hd )
pixhawk's avatar
pixhawk committed
140 141 142 143 144 145 146 147 148 149
{
    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
150
  \sa setHand()
pixhawk's avatar
pixhawk committed
151
*/
Bryant's avatar
Bryant committed
152
const QwtDialNeedle *QwtAnalogClock::hand( Hand hd ) const
pixhawk's avatar
pixhawk committed
153
{
Bryant's avatar
Bryant committed
154
    return const_cast<QwtAnalogClock *>( this )->hand( hd );
pixhawk's avatar
pixhawk committed
155 156 157 158 159 160
}

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

/*!
166
  Set a time
pixhawk's avatar
pixhawk committed
167 168
  \param time Time to display
*/
Bryant's avatar
Bryant committed
169
void QwtAnalogClock::setTime( const QTime &time )
pixhawk's avatar
pixhawk committed
170
{
Bryant's avatar
Bryant committed
171 172 173 174 175 176 177
    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
178 179 180 181 182
}

/*!
  \brief Draw the needle

Bryant's avatar
Bryant committed
183
  A clock has no single needle but three hands instead. drawNeedle()
pixhawk's avatar
pixhawk committed
184 185 186 187 188 189
  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
190 191
  \param dir Dummy, not used.
  \param colorGroup ColorGroup
pixhawk's avatar
pixhawk committed
192

Bryant's avatar
Bryant committed
193
  \sa drawHand()
pixhawk's avatar
pixhawk committed
194
*/
Bryant's avatar
Bryant committed
195 196
void QwtAnalogClock::drawNeedle( QPainter *painter, const QPointF &center,
    double radius, double dir, QPalette::ColorGroup colorGroup ) const
pixhawk's avatar
pixhawk committed
197
{
Bryant's avatar
Bryant committed
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
    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
219 220 221 222 223 224 225 226 227 228 229 230 231
    }
}

/*!
  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
232 233 234
void QwtAnalogClock::drawHand( QPainter *painter, Hand hd,
    const QPointF &center, double radius, double direction,
    QPalette::ColorGroup cg ) const
pixhawk's avatar
pixhawk committed
235
{
Bryant's avatar
Bryant committed
236 237 238
    const QwtDialNeedle *needle = hand( hd );
    if ( needle )
    {
pixhawk's avatar
pixhawk committed
239
        if ( hd == HourHand )
Bryant's avatar
Bryant committed
240
            radius = qRound( 0.8 * radius );
pixhawk's avatar
pixhawk committed
241

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