Commands.cpp 9.68 KB
Newer Older
1 2 3
/*****************************************************************************
 * Commands.cpp: Contains all the implementation of VLMC commands.
 *****************************************************************************
Ludovic Fauvet's avatar
Ludovic Fauvet committed
4
 * Copyright (C) 2008-2010 VideoLAN
5
 *
6
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *          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.
 *****************************************************************************/

24 25
#include "Commands.h"

26 27
#include "config.h"
#include "Clip.h"
28
#include "ClipHelper.h"
29
#include "EffectHelper.h"
30
#include "EffectInstance.h"
31
#include "MainWorkflow.h"
32
#include "TrackWorkflow.h"
33 34 35

#ifdef WITH_GUI
# include "UndoStack.h"
36

37 38
void
Commands::trigger( QUndoCommand* command )
39 40 41
{
    UndoStack::getInstance()->push( command );
}
42
#else
43 44
void
Commands::trigger( Commands::Generic* command )
45 46 47 48 49
{
    command->redo();
}
#endif

50 51 52
Commands::Generic::Generic() :
        m_valid( true )
{
53 54 55 56
    //This is connected using a direct connection to ensure the view can be refreshed
    //just after the signal has been emited.
    connect( UndoStack::getInstance(), SIGNAL( retranslateRequired() ),
             this, SLOT( retranslate() ), Qt::DirectConnection );
57
}
58

59 60 61
void
Commands::Generic::invalidate()
{
62
    setText( tr( "Invalid action" ) );
63
    m_valid = false;
64
    emit invalidated();
65 66 67 68 69 70 71
}

bool
Commands::Generic::isValid() const
{
    return m_valid;
}
72

73 74 75 76 77 78 79 80 81 82 83 84 85 86
void
Commands::Generic::redo()
{
    if ( m_valid == true )
        internalRedo();
}

void
Commands::Generic::undo()
{
    if ( m_valid == true )
        internalUndo();
}

87
Commands::Clip::Add::Add( ClipHelper* ch, TrackWorkflow* tw, qint64 pos ) :
88
        m_clipHelper( ch ),
89 90
        m_trackWorkflow( tw ),
        m_pos( pos )
91
{
92
    connect( ch->clip(), SIGNAL( destroyed() ), this, SLOT( invalidate() ) );
93
    retranslate();
94 95
}

96
Commands::Clip::Add::~Add()
97 98 99
{
}

100 101
void
Commands::Clip::Add::internalRedo()
102
{
103
    m_trackWorkflow->addClip( m_clipHelper, m_pos );
104 105
}

106 107
void
Commands::Clip::Add::internalUndo()
108
{
109
    m_trackWorkflow->removeClip( m_clipHelper->uuid() );
110 111
}

112 113 114 115 116 117
void
Commands::Clip::Add::retranslate()
{
    setText( tr( "Adding clip to track %1" ).arg( m_trackWorkflow->trackId() ) );
}

118
Commands::Clip::Move::Move( TrackWorkflow *oldTrack, TrackWorkflow *newTrack,
119 120 121 122 123 124
                                            ClipHelper *clipHelper, qint64 newPos ) :
    m_oldTrack( oldTrack ),
    m_newTrack( newTrack ),
    m_clipHelper( clipHelper ),
    m_newPos( newPos )

125
{
126 127
    Q_ASSERT( oldTrack->type() == newTrack->type() );

128 129 130 131 132 133 134 135 136 137 138
    m_oldPos = oldTrack->getClipPosition( clipHelper->uuid() );
    connect( clipHelper->clip(), SIGNAL( destroyed() ), this, SLOT( invalidate() ) );
    retranslate();
}

void
Commands::Clip::Move::retranslate()
{
    if ( m_oldTrack != m_newTrack )
        setText( tr( "Moving clip from track %1 to %2" ).arg(
                QString::number( m_oldTrack->trackId() ), QString::number( m_newTrack->trackId() ) ) );
139 140
    else
        setText( QObject::tr( "Moving clip" ) );
141 142
}

143 144
void
Commands::Clip::Move::internalRedo()
145
{
146 147
    if ( m_newTrack != m_oldTrack )
    {
148 149
        ClipWorkflow    *cw = m_oldTrack->removeClipWorkflow( m_clipHelper->uuid() );
        m_newTrack->addClip( cw, m_newPos );
150 151 152
    }
    else
        m_oldTrack->moveClip( m_clipHelper->uuid(), m_newPos );
153 154
}

155 156
void
Commands::Clip::Move::internalUndo()
157
{
158 159
    if ( m_newTrack != m_oldTrack )
    {
160 161
        ClipWorkflow    *cw = m_newTrack->removeClipWorkflow( m_clipHelper->uuid() );
        m_oldTrack->addClip( cw, m_oldPos );
162 163 164
    }
    else
        m_newTrack->moveClip( m_clipHelper->uuid(), m_oldPos );
165 166
}

167
Commands::Clip::Remove::Remove( ClipHelper* ch, TrackWorkflow* tw ) :
168
        m_clipHelper( ch ), m_trackWorkflow( tw )
169
{
170
    connect( ch->clip(), SIGNAL( destroyed() ), this, SLOT( invalidate() ) );
171
    retranslate();
172
    m_pos = tw->getClipPosition( ch->uuid() );
173
}
174

175 176 177 178 179 180 181 182
void
Commands::Clip::Remove::retranslate()
{
   setText( tr( "Removing clip " ) );
}

void
Commands::Clip::Remove::internalRedo()
183
{
184
    m_trackWorkflow->removeClip( m_clipHelper->uuid() );
185
}
186

187 188
void
Commands::Clip::Remove::internalUndo()
189
{
190
    m_trackWorkflow->addClip( m_clipHelper, m_pos );
191 192
}

193 194
Commands::Clip::Resize::Resize( TrackWorkflow* tw, ClipHelper* ch, qint64 newBegin,
                                qint64 newEnd, qint64 newPos ) :
195 196
    m_trackWorkflow( tw ),
    m_clipHelper( ch ),
197
    m_newBegin( newBegin ),
198
    m_newEnd( newEnd ),
199
    m_newPos( newPos )
200
{
201
    connect( ch->clip(), SIGNAL( destroyed() ), this, SLOT( invalidate() ) );
202 203 204
    m_oldBegin = ch->begin();
    m_oldEnd = ch->end();
    m_oldPos = tw->getClipPosition( ch->uuid() );
205 206 207 208 209 210 211
    retranslate();
}

void
Commands::Clip::Resize::retranslate()
{
    setText( tr( "Resizing clip" ) );
212 213
}

214 215
void
Commands::Clip::Resize::internalRedo()
216
{
217 218 219 220 221
    if ( m_newBegin != m_newEnd )
    {
        m_trackWorkflow->moveClip( m_clipHelper->uuid(), m_newPos );
    }
    m_clipHelper->setBoundaries( m_newBegin, m_newEnd );
222 223
}

224 225
void
Commands::Clip::Resize::internalUndo()
226
{
227
    if ( m_oldBegin != m_newBegin )
228
    {
229
        m_trackWorkflow->moveClip( m_clipHelper->uuid(), m_oldPos );
230
    }
231
    m_clipHelper->setBoundaries( m_oldBegin, m_oldEnd );
232
}
233

234
Commands::Clip::Split::Split( TrackWorkflow *tw, ClipHelper *toSplit,
235 236
                                             qint64 newClipPos, qint64 newClipBegin ) :
    m_trackWorkflow( tw ),
237 238 239
    m_toSplit( toSplit ),
    m_newClip( NULL ),
    m_newClipPos( newClipPos ),
240
    m_newClipBegin( newClipBegin )
241
{
242
    connect( toSplit->clip(), SIGNAL( destroyed() ), this, SLOT( invalidate() ) );
243 244
    m_newClip = new ClipHelper( toSplit->clip(), newClipBegin, toSplit->end() );
    m_oldEnd = toSplit->end();
245
    retranslate();
246 247
}

248
Commands::Clip::Split::~Split()
249
{
250
    delete m_newClip;
251
}
252

253 254 255 256 257 258 259 260
void
Commands::Clip::Split::retranslate()
{
    setText( tr("Splitting clip") );
}

void
Commands::Clip::Split::internalRedo()
261
{
262 263
    //If we don't remove 1, the clip will end exactly at the starting frame (ie. they will
    //be rendering at the same time)
264
    m_toSplit->setEnd( m_newClipBegin );
265
    m_trackWorkflow->addClip( m_newClip, m_newClipPos );
266 267
}

268 269
void
Commands::Clip::Split::internalUndo()
270
{
271 272
    m_trackWorkflow->removeClip( m_newClip->uuid() );
    m_toSplit->setEnd( m_oldEnd );
273
}
274

275 276 277 278
Commands::Effect::Add::Add( EffectHelper *helper, EffectUser *target ) :
        m_helper( helper ),
        m_target( target )
{
279 280 281 282 283 284 285
    retranslate();
}

void
Commands::Effect::Add::retranslate()
{
    setText( tr( "Adding effect %1" ).arg( m_helper->effectInstance()->effect()->name() ) );
286 287 288
}

void
289
Commands::Effect::Add::internalRedo()
290 291 292 293 294
{
    m_target->addEffect( m_helper );
}

void
295
Commands::Effect::Add::internalUndo()
296 297 298 299
{
    m_target->removeEffect( m_helper );
}

300 301 302 303 304 305 306 307
Commands::Effect::Move::Move( EffectHelper *helper, EffectUser *old, EffectUser *newUser,
                              qint64 pos) :
    m_helper( helper ),
    m_old( old ),
    m_new( newUser ),
    m_newPos( pos )
{
    m_oldPos = helper->begin();
308 309
    m_oldEnd = helper->end();
    m_newEnd = m_helper->end() - ( m_helper->begin() - pos );
310 311 312 313 314 315 316
    retranslate();
}

void
Commands::Effect::Move::retranslate()
{
    setText( tr( "Moving effect %1" ).arg( m_helper->effectInstance()->effect()->name() ) );
317 318 319
}

void
320
Commands::Effect::Move::internalRedo()
321 322 323 324
{
    if ( m_old != m_new )
    {
        m_old->removeEffect( m_helper );
325
        m_helper->setBoundaries( m_newPos, m_newEnd );
326
        m_new->addEffect( m_helper );
327

328 329 330 331 332 333
    }
    else
        m_new->moveEffect( m_helper, m_newPos );
}

void
334
Commands::Effect::Move::internalUndo()
335 336 337 338
{
    if ( m_old != m_new )
    {
        m_new->removeEffect( m_helper );
339 340
        m_helper->setBoundaries( m_oldPos, m_oldEnd );
        //This must be called after setting boundaries, as the effect's begin is its begin boundary
341 342 343 344 345
        m_old->addEffect( m_helper );
    }
    else
        m_new->moveEffect( m_helper, m_oldPos );
}
346

347 348
Commands::Effect::Resize::Resize( EffectUser *target, EffectHelper *helper, qint64 newBegin, qint64 newEnd ) :
        m_target( target ),
349 350 351 352 353 354
        m_helper( helper ),
        m_newBegin( newBegin ),
        m_newEnd( newEnd )
{
    m_oldBegin = helper->begin();
    m_oldEnd = helper->end();
355 356 357 358 359 360 361
    retranslate();
}

void
Commands::Effect::Resize::retranslate()
{
    setText( tr( "Resizing effect %1" ).arg( m_helper->effectInstance()->effect()->name() ) );
362 363 364
}

void
365
Commands::Effect::Resize::internalRedo()
366
{
367 368
    if ( m_newBegin != m_oldBegin )
        m_target->moveEffect( m_helper, m_newBegin );
369 370 371 372
    m_helper->setBoundaries( m_newBegin, m_newEnd );
}

void
373
Commands::Effect::Resize::internalUndo()
374
{
375 376
    if ( m_oldBegin != m_newBegin )
        m_target->moveEffect( m_helper, m_oldBegin );
377 378
    m_helper->setBoundaries( m_oldBegin, m_oldEnd );
}
379 380 381 382 383

Commands::Effect::Remove::Remove( EffectHelper *helper, EffectUser *user ) :
        m_helper( helper ),
        m_user( user )
{
384 385 386 387 388 389 390
    retranslate();
}

void
Commands::Effect::Remove::retranslate()
{
    setText( tr( "Deleting effect %1" ).arg( m_helper->effectInstance()->effect()->name() ) );
391 392 393
}

void
394
Commands::Effect::Remove::internalRedo()
395 396 397 398 399
{
    m_user->removeEffect( m_helper );
}

void
400
Commands::Effect::Remove::internalUndo()
401 402 403
{
    m_user->addEffect( m_helper );
}