GraphicsMovieItem.cpp 7.46 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*****************************************************************************
 * GraphicsMovieItem.cpp: Represent a movie graphically in the timeline
 *****************************************************************************
 * Copyright (C) 2008-2009 the VLMC team
 *
 * 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.
 *****************************************************************************/

23
#include <QPainter>
24
#include <QLinearGradient>
25
#include <QDebug>
Ludovic Fauvet's avatar
Ludovic Fauvet committed
26
#include <QTime>
27 28
#include "GraphicsMovieItem.h"
#include "TracksView.h"
29
#include "Timeline.h"
30

31
GraphicsMovieItem::GraphicsMovieItem( Clip* clip ) : m_clip( clip )
32
{
33 34
    setFlags( QGraphicsItem::ItemIsSelectable );

35
    QTime length = QTime().addMSecs( clip->getParent()->getLengthMS() );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
36 37
    QString tooltip( tr( "<p style='white-space:pre'><b>Name:</b> %1"
                     "<br><b>Length:</b> %2" )
38
                     .arg( clip->getParent()->getFileName() )
Ludovic Fauvet's avatar
Ludovic Fauvet committed
39
                     .arg( length.toString("hh:mm:ss.zzz") ) );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
40
    setToolTip( tooltip );
41
    setAcceptHoverEvents( true );
42 43 44

    // Adjust the width
    setWidth( clip->getLength() );
45
    // Automatically adjust for future changes
46
    connect( clip, SIGNAL( lengthUpdated() ), this, SLOT( adjustLength() ) );
47 48 49 50 51 52
}

GraphicsMovieItem::~GraphicsMovieItem()
{
}

53 54 55 56 57
MainWorkflow::TrackType GraphicsMovieItem::mediaType() const
{
    return MainWorkflow::VideoTrack;
}

58
void GraphicsMovieItem::paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* )
59
{
60
    painter->save();
61
    paintRect( painter, option );
62
    painter->restore();
63

64
    painter->save();
65
    paintTitle( painter, option );
66
    painter->restore();
67 68
}

69
Clip* GraphicsMovieItem::clip() const
70
{
71
    return m_clip;
72
}
73

74
void GraphicsMovieItem::paintRect( QPainter* painter, const QStyleOptionGraphicsItem* option )
75
{
76 77 78
    QRectF drawRect;
    bool drawRound;

79 80 81 82 83 84 85
    // Disable the matrix transformations
    painter->setWorldMatrixEnabled( false );

    painter->setRenderHint( QPainter::Antialiasing );

    // Get the transformations required to map the text on the viewport
    QTransform viewPortTransform = Timeline::getInstance()->tracksView()->viewportTransform();
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104

    // Determine if a drawing optimization can be used
    if ( option->exposedRect.left() > ROUNDED_RECT_RADIUS &&
         option->exposedRect.right() < boundingRect().right() - ROUNDED_RECT_RADIUS )
    {
        // Optimized: paint only the exposed (horizontal) area
        drawRect = QRectF( option->exposedRect.left(),
                           boundingRect().top(),
                           option->exposedRect.right(),
                           boundingRect().bottom() );
        drawRound = false;
    }
    else
    {
        // Unoptimized: the item must be fully repaint
        drawRect = boundingRect();
        drawRound = true;
    }

105
    // Do the transformation
106
    QRectF mapped = deviceTransform( viewPortTransform ).mapRect( drawRect );
107 108 109 110 111 112 113 114 115

    QLinearGradient gradient( mapped.topLeft(), mapped.bottomLeft() );
    gradient.setColorAt( 0, QColor::fromRgb( 78, 78, 78 ) );
    gradient.setColorAt( 0.4, QColor::fromRgb( 72, 72, 72 ) );
    gradient.setColorAt( 0.4, QColor::fromRgb( 50, 50, 50 ) );
    gradient.setColorAt( 1, QColor::fromRgb( 45, 45, 45 ) );

    painter->setPen( Qt::NoPen );
    painter->setBrush( QBrush( gradient ) );
116 117 118 119 120

    if ( drawRound )
        painter->drawRoundedRect( mapped, ROUNDED_RECT_RADIUS, ROUNDED_RECT_RADIUS );
    else
        painter->drawRect( mapped );
121 122 123 124 125

    if ( isSelected() )
    {
        setZValue( Z_SELECTED );
        painter->setPen( Qt::yellow );
126 127 128 129 130 131
        painter->setBrush( Qt::NoBrush );
        mapped.adjust( 0, 0, 0, -1 );
        if ( drawRound )
            painter->drawRoundedRect( mapped, ROUNDED_RECT_RADIUS, ROUNDED_RECT_RADIUS );
        else
            painter->drawRect( mapped );
132 133 134 135 136
    }
    else
        setZValue( Z_NOT_SELECTED );
}

137
void GraphicsMovieItem::paintTitle( QPainter* painter, const QStyleOptionGraphicsItem* option )
138
{
139 140
    Q_UNUSED( option );

141 142 143 144 145 146 147 148 149 150
    // Disable the matrix transformations
    painter->setWorldMatrixEnabled( false );

    // Setup the font
    QFont f = painter->font();
    f.setPointSize( 8 );
    painter->setFont( f );

    // Initiate the font metrics calculation
    QFontMetrics fm( painter->font() );
151
    QString text = m_clip->getParent()->getFileName();
152

153 154 155 156 157 158
    // Get the transformations required to map the text on the viewport
    QTransform viewPortTransform = Timeline::getInstance()->tracksView()->viewportTransform();
    // Do the transformation
    QRectF mapped = deviceTransform( viewPortTransform ).mapRect( boundingRect() );
    // Create an inner rect
    mapped.adjust( 2, 2, -2, -2 );
159

160 161
    painter->setPen( Qt::white );
    painter->drawText( mapped, Qt::AlignVCenter, fm.elidedText( text, Qt::ElideRight, mapped.width() ) );
162
}
163 164 165 166 167 168 169 170 171

void GraphicsMovieItem::hoverEnterEvent( QGraphicsSceneHoverEvent* event )
{
    TracksView* tv = Timeline::getInstance()->tracksView();
    if ( tv )
    {
        switch ( tv->tool() )
        {
            case TOOL_DEFAULT:
172
            setCursor( Qt::OpenHandCursor );
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
            break;

            case TOOL_CUT:
            setCursor( QCursor( QPixmap( ":/images/editcut" ) ) );
            break;
        }
    }

    AbstractGraphicsMediaItem::hoverEnterEvent( event );
}

void GraphicsMovieItem::hoverLeaveEvent( QGraphicsSceneHoverEvent* event )
{
    AbstractGraphicsMediaItem::hoverLeaveEvent( event );
}
188

Ludovic Fauvet's avatar
Ludovic Fauvet committed
189 190 191 192 193 194
void GraphicsMovieItem::hoverMoveEvent( QGraphicsSceneHoverEvent* event )
{
    if ( !tracksView() ) return;

    if ( tracksView()->tool() == TOOL_DEFAULT )
    {
195
        if ( resizeZone( event->pos() ) )
Ludovic Fauvet's avatar
Ludovic Fauvet committed
196 197 198 199 200 201
            setCursor( Qt::SizeHorCursor );
        else
            setCursor( Qt::OpenHandCursor );
    }
}

202 203
void GraphicsMovieItem::mousePressEvent( QGraphicsSceneMouseEvent* event )
{
Ludovic Fauvet's avatar
Ludovic Fauvet committed
204 205 206
    if ( !tracksView() ) return;

    if ( tracksView()->tool() == TOOL_DEFAULT )
207 208 209 210 211 212
    {
        if ( resizeZone( event->pos() ) )
            setCursor( Qt::SizeHorCursor );
        else
            setCursor( Qt::ClosedHandCursor );
    }
Ludovic Fauvet's avatar
Ludovic Fauvet committed
213
    else if ( tracksView()->tool() == TOOL_CUT )
214 215 216 217 218 219
        emit split( this, qRound64( event->pos().x() ) );
}

void GraphicsMovieItem::mouseReleaseEvent( QGraphicsSceneMouseEvent*  event )
{
    Q_UNUSED( event );
Ludovic Fauvet's avatar
Ludovic Fauvet committed
220 221 222
    if ( !tracksView() ) return;

    if ( tracksView()->tool() == TOOL_DEFAULT )
223 224
        setCursor( Qt::OpenHandCursor );
}
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

bool GraphicsMovieItem::resizeZone( const QPointF& position )
{
    // Get the current transformation of the view and invert it.
    QTransform transform = tracksView()->transform().inverted();
    // Map the RESIZE_ZONE distance from the view to the item coordinates.
    QLine line = transform.map( QLine( 0, 0, RESIZE_ZONE, 0 ) );

    if ( position.x() < line.x2() ||
         position.x() > ( boundingRect().width() - line.x2() ) )
    {
        return true;
    }
    return false;
}