TracksRuler.cpp 6.92 KB
Newer Older
Ludovic Fauvet's avatar
Ludovic Fauvet committed
1
2
3
/*****************************************************************************
 * TracksRuler.cpp: Timeline ruler
 *****************************************************************************
Ludovic Fauvet's avatar
Ludovic Fauvet committed
4
 * Copyright (C) 2008-2010 VideoLAN
Ludovic Fauvet's avatar
Ludovic Fauvet committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 *
 * Authors: Ludovic Fauvet <etix@l0cal.com>
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include <QStylePainter>
#include <QBrush>
#include <QColor>
#include <QPalette>
Ludovic Fauvet's avatar
Ludovic Fauvet committed
27
#include <QPolygon>
Ludovic Fauvet's avatar
Ludovic Fauvet committed
28
#include "TracksRuler.h"
Ludovic Fauvet's avatar
Ludovic Fauvet committed
29
#include "TracksView.h"
30
#include "SettingsManager.h"
Ludovic Fauvet's avatar
Ludovic Fauvet committed
31
32
33

const int TracksRuler::comboScale[] = { 1, 2, 5, 10, 25, 50, 125, 250, 500, 725, 1500, 3000, 6000, 12000};

Ludovic Fauvet's avatar
Ludovic Fauvet committed
34
TracksRuler::TracksRuler( TracksView* tracksView, QWidget* parent )
Ludovic Fauvet's avatar
Ludovic Fauvet committed
35
    : QWidget( parent ), m_tracksView( tracksView ), m_duration ( 0 ), m_offset( 0 )
Ludovic Fauvet's avatar
Ludovic Fauvet committed
36
{
37
38
39

    //TODO We should really get that from the
    // workflow and not directly from the settings.
40
    m_fps = qRound( VLMC_PROJECT_GET_DOUBLE( "video/VLMCOutputFPS" ) );
41

Ludovic Fauvet's avatar
Ludovic Fauvet committed
42
43
44
45
46
    m_factor = 1;
    m_scale = 3;
    m_littleMarkDistance = FRAME_SIZE;
    m_mediumMarkDistance = FRAME_SIZE * m_fps;
    m_bigMarkDistance = FRAME_SIZE * m_fps * 60;
Ludovic Fauvet's avatar
Ludovic Fauvet committed
47
    setMinimumHeight( 30 );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
48
    setPixelPerMark( 5 );
49
50

    // Redraw the ruler when the cursor position change
51
    connect( tracksView->tracksCursor(), SIGNAL( cursorPositionChanged(qint64) ),
52
             this, SLOT( update() ) );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
}

void TracksRuler::setPixelPerMark( double rate )
{
    int scale = comboScale[ ( int )rate ];
    m_factor = 1.0 / ( double ) scale * FRAME_SIZE;
    m_scale = 1.0 / ( double ) scale;
    double fend = m_scale * m_littleMarkDistance;

    switch ( ( int )rate )
    {
    case 0:
        m_textSpacing = fend;
        break;
    case 1:
        m_textSpacing = fend * m_fps;
        break;
    case 2:
    case 3:
    case 4:
        m_textSpacing = fend * m_fps * 5;
        break;
    case 5:
    case 6:
        m_textSpacing = fend * m_fps * 10;
        break;
    case 7:
        m_textSpacing = fend * m_fps * 30;
        break;
    case 8:
    case 9:
    case 10:
        m_textSpacing = fend * m_fps * 60;
        break;
    case 11:
    case 12:
        m_textSpacing = fend * m_fps * 300;
        break;
    case 13:
        m_textSpacing = fend * m_fps * 600;
        break;
    }
    update();
}

void TracksRuler::setDuration( int duration )
{
    int oldDuration = m_duration;
    m_duration = duration;
102

Ludovic Fauvet's avatar
Ludovic Fauvet committed
103
    Q_UNUSED( oldDuration );
104
105
106
107
108
109
    //FIXME The optimized update() version cause wrong values to be shown in
    //the ruler. I don't understand what's happening here.

    /*update( ( int ) ( qMin( oldDuration, m_duration ) * m_factor - 1 - m_offset ), 0,
            ( int ) ( qAbs( oldDuration - m_duration ) * m_factor + 2 ), height() );*/
    update();
Ludovic Fauvet's avatar
Ludovic Fauvet committed
110
111
112
113
114
115
116
117
118
}

void TracksRuler::paintEvent( QPaintEvent* e )
{
    QStylePainter painter( this );
    painter.setClipRect( e->rect() );

    // Draw the background
    const int projectEnd = ( int )( m_duration * m_factor );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
119
120
    if ( projectEnd - m_offset > 1 )
        painter.fillRect( 0, 0, projectEnd - m_offset, height(), QBrush( QColor( 245, 245, 245 ) ) );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
121
122
123
124
125
126
127
128
129
130


    double f, step;
    int offsetMax;
    int offsetMin;
    const int maxVal = ( e->rect().right() + m_offset ) / FRAME_SIZE + 1;
    offsetMax = maxVal * FRAME_SIZE;

    QPalette palette;
    painter.setPen( palette.dark().color() );
131
132
    offsetMin = ( int ) ( ( e->rect().left() + m_offset ) / m_textSpacing );
    offsetMin = ( int ) ( offsetMin * m_textSpacing );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
133
134
    for ( f = offsetMin; f < offsetMax; f += m_textSpacing )
    {
135
        QString time = getTimeCode( (int)( f / m_factor + 0.5 ) );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
136
        painter.drawText( ( int )f - m_offset + 2, LABEL_SIZE + 1, time );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
    }


    // Draw the marks
    offsetMin = ( e->rect().left() + m_offset ) / m_littleMarkDistance;
    offsetMin = offsetMin * m_littleMarkDistance;
    step = m_scale * m_littleMarkDistance;
    if ( step > 5 )
        for ( f = offsetMin - m_offset; f < offsetMax - m_offset; f += step )
            painter.drawLine( ( int )f, LITTLE_MARK_X1, ( int )f, LITTLE_MARK_X2 );

    offsetMin = ( e->rect().left() + m_offset ) / m_mediumMarkDistance;
    offsetMin = offsetMin * m_mediumMarkDistance;
    step = m_scale * m_mediumMarkDistance;
    if ( step > 5 )
        for ( f = offsetMin - m_offset; f < offsetMax - m_offset; f += step )
            painter.drawLine( ( int )f, MIDDLE_MARK_X1, ( int )f, MIDDLE_MARK_X2 );

    offsetMin = ( e->rect().left() + m_offset ) / m_bigMarkDistance;
    offsetMin = offsetMin * m_bigMarkDistance;
    step = m_scale * m_bigMarkDistance;
    if ( step > 5 )
        for ( f = offsetMin - m_offset; f < offsetMax - m_offset; f += step )
            painter.drawLine( ( int )f, BIG_MARK_X1, ( int )f, BIG_MARK_X2 );

Ludovic Fauvet's avatar
Ludovic Fauvet committed
162
    // Draw the pointer
163
    int cursorPos = m_tracksView->cursorPos() * m_factor - offset();
Ludovic Fauvet's avatar
Ludovic Fauvet committed
164
165
166
167
    QPolygon cursor( 3 );
    cursor.setPoints( 3, cursorPos - 9, 11, cursorPos + 9, 11, cursorPos, 30 );
    painter.setBrush( QBrush( QColor( 82, 97, 122, 150 ) ) );
    painter.drawPolygon( cursor );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
168
169
}

170
171
172
173
174
void TracksRuler::mousePressEvent( QMouseEvent* event )
{
    if ( event->buttons() == Qt::LeftButton &&
         event->modifiers() == Qt::NoModifier )
    {
Ludovic Fauvet's avatar
Ludovic Fauvet committed
175
        emit frameChanged( qMax( (qreal)0, (qreal)( event->x() + offset() ) / m_factor ), MainWorkflow::RulerCursor );
176
177
178
179
180
181
182
183
    }
}

void TracksRuler::mouseMoveEvent( QMouseEvent* event )
{
    if ( event->buttons() == Qt::LeftButton &&
         event->modifiers() == Qt::NoModifier )
    {
Ludovic Fauvet's avatar
Ludovic Fauvet committed
184
        emit frameChanged( qMax( (qreal)0, (qreal)( event->x() + offset() ) / m_factor ), MainWorkflow::RulerCursor );
185
186
187
    }
}

188
void        TracksRuler::moveRuler( int pos )
Ludovic Fauvet's avatar
Ludovic Fauvet committed
189
190
191
192
{
    m_offset = pos;
    update();
}
193

194
QString     TracksRuler::getTimeCode( int frames ) const
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
{
    int seconds = frames / m_fps;
    frames = frames % m_fps;

    int minutes = seconds / 60;
    seconds = seconds % 60;
    int hours = minutes / 60;
    minutes = minutes % 60;

    QString text;

    text.append( QString::number( hours ).rightJustified( 2, '0', false ) );
    text.append( ':' );
    text.append( QString::number( minutes ).rightJustified( 2, '0', false ) );
    text.append( ':' );
    text.append( QString::number( seconds ).rightJustified( 2, '0', false ) );
    text.append( ':' );
    text.append( QString::number( frames ).rightJustified( 2, '0', false ) );
    return text;
}