Revised journalling (undo/redo) to record full states instead of changes
Recording single changes of objects or their specific properties is completely superfluous as we have full implemented state tracking in all objects already. Therefore use SerializingObject::saveState() and SerializingObject::restoreState() in order to implement the undo/redo functionality. This is just an initial commit and needs some further work (especially regarding stability). However even things like undo/redo of addition/removal of Tracks and TrackContentObjects do work already.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* AutomatableModel.cpp - some implementations of AutomatableModel-class
|
||||
*
|
||||
* Copyright (c) 2008-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -50,7 +50,6 @@ AutomatableModel::AutomatableModel( DataType _type,
|
||||
m_maxValue( _max ),
|
||||
m_step( _step ),
|
||||
m_range( _max - _min ),
|
||||
m_journalEntryReady( false ),
|
||||
m_setValueDepth( 0 ),
|
||||
m_hasLinkedModels( false ),
|
||||
m_controllerConnection( NULL )
|
||||
@@ -88,6 +87,22 @@ bool AutomatableModel::isAutomated() const
|
||||
|
||||
|
||||
|
||||
void AutomatableModel::saveSettings( QDomDocument &doc, QDomElement &_this )
|
||||
{
|
||||
saveSettings( doc, _this, "value" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AutomatableModel::loadSettings( const QDomElement &_this )
|
||||
{
|
||||
loadSettings( _this, "value" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AutomatableModel::saveSettings( QDomDocument & _doc, QDomElement & _this,
|
||||
const QString & _name )
|
||||
{
|
||||
@@ -184,7 +199,7 @@ void AutomatableModel::setValue( const float _value )
|
||||
if( old_val != m_value )
|
||||
{
|
||||
// add changes to history so user can undo it
|
||||
addJournalEntry( JournalEntry( 0, m_value - old_val ) );
|
||||
addJournalCheckPoint();
|
||||
|
||||
// notify linked models
|
||||
for( AutoModelVector::Iterator it =
|
||||
@@ -319,52 +334,6 @@ float AutomatableModel::fittedValue( float _value ) const
|
||||
|
||||
|
||||
|
||||
void AutomatableModel::redoStep( JournalEntry & _je )
|
||||
{
|
||||
bool journalling = testAndSetJournalling( false );
|
||||
setValue( value<float>() + (float) _je.data().toDouble() );
|
||||
setJournalling( journalling );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AutomatableModel::undoStep( JournalEntry & _je )
|
||||
{
|
||||
JournalEntry je( _je.actionID(), -_je.data().toDouble() );
|
||||
redoStep( je );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AutomatableModel::prepareJournalEntryFromOldVal()
|
||||
{
|
||||
m_oldValue = value<float>();
|
||||
saveJournallingState( false );
|
||||
m_journalEntryReady = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AutomatableModel::addJournalEntryFromOldToCurVal()
|
||||
{
|
||||
if( m_journalEntryReady )
|
||||
{
|
||||
restoreJournallingState();
|
||||
if( value<float>() != m_oldValue )
|
||||
{
|
||||
addJournalEntry( JournalEntry( 0, value<float>() -
|
||||
m_oldValue ) );
|
||||
}
|
||||
m_journalEntryReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void AutomatableModel::linkModel( AutomatableModel * _model )
|
||||
{
|
||||
if( !m_linkedModels.contains( _model ) )
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* JournallingObject.cpp - implementation of journalling-object related stuff
|
||||
*
|
||||
* Copyright (c) 2006-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -37,8 +37,8 @@
|
||||
JournallingObject::JournallingObject() :
|
||||
SerializingObject(),
|
||||
m_id( engine::projectJournal()->allocID( this ) ),
|
||||
m_journalEntries(),
|
||||
m_currentJournalEntry( m_journalEntries.end() ),
|
||||
m_journalCheckPoints(),
|
||||
m_currentJournalCheckPoint( m_journalCheckPoints.end() ),
|
||||
m_journalling( true ),
|
||||
m_journallingStateStack()
|
||||
{
|
||||
@@ -60,14 +60,15 @@ JournallingObject::~JournallingObject()
|
||||
|
||||
void JournallingObject::undo()
|
||||
{
|
||||
if( m_journalEntries.empty() == true )
|
||||
if( m_journalCheckPoints.empty() == true )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_currentJournalEntry - 1 >= m_journalEntries.begin() )
|
||||
if( m_currentJournalCheckPoint - 1 >= m_journalCheckPoints.begin() )
|
||||
{
|
||||
undoStep( *--m_currentJournalEntry );
|
||||
--m_currentJournalCheckPoint;
|
||||
restoreState( m_currentJournalCheckPoint->data().content().firstChildElement() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,14 +77,15 @@ void JournallingObject::undo()
|
||||
|
||||
void JournallingObject::redo()
|
||||
{
|
||||
if( m_journalEntries.empty() == true )
|
||||
if( m_journalCheckPoints.empty() == true )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_currentJournalEntry < m_journalEntries.end() )
|
||||
if( m_currentJournalCheckPoint < m_journalCheckPoints.end() )
|
||||
{
|
||||
redoStep( *m_currentJournalEntry++ );
|
||||
restoreState( m_currentJournalCheckPoint->data().content().firstChildElement() );
|
||||
++m_currentJournalCheckPoint;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,14 +126,19 @@ void JournallingObject::restoreState( const QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
void JournallingObject::addJournalEntry( const JournalEntry & _je )
|
||||
void JournallingObject::addJournalCheckPoint()
|
||||
{
|
||||
if( engine::projectJournal()->isJournalling() && isJournalling() )
|
||||
{
|
||||
m_journalEntries.erase( m_currentJournalEntry,
|
||||
m_journalEntries.end() );
|
||||
m_journalEntries.push_back( _je );
|
||||
m_currentJournalEntry = m_journalEntries.end();
|
||||
m_journalCheckPoints.erase( m_currentJournalCheckPoint,
|
||||
m_journalCheckPoints.end() );
|
||||
|
||||
multimediaProject mmp( multimediaProject::JournalData );
|
||||
saveState( mmp, mmp.content() );
|
||||
|
||||
m_journalCheckPoints.push_back( JournalCheckPoint( mmp ) );
|
||||
|
||||
m_currentJournalCheckPoint = m_journalCheckPoints.end();
|
||||
engine::projectJournal()->journalEntryAdded( id() );
|
||||
}
|
||||
}
|
||||
@@ -172,25 +179,25 @@ void JournallingObject::saveJournal( QDomDocument & _doc,
|
||||
QDomElement & _parent )
|
||||
{
|
||||
/* // avoid creating empty journal-nodes
|
||||
if( m_journalEntries.size() == 0 )
|
||||
if( m_journalCheckPoints.size() == 0 )
|
||||
{
|
||||
return;
|
||||
}*/
|
||||
QDomElement journal_de = _doc.createElement( "journal" );
|
||||
journal_de.setAttribute( "id", id() );
|
||||
journal_de.setAttribute( "entries", m_journalEntries.size() );
|
||||
journal_de.setAttribute( "curentry", (int)( m_currentJournalEntry -
|
||||
m_journalEntries.begin() ) );
|
||||
journal_de.setAttribute( "entries", m_journalCheckPoints.size() );
|
||||
journal_de.setAttribute( "curentry", (int)( m_currentJournalCheckPoint -
|
||||
m_journalCheckPoints.begin() ) );
|
||||
journal_de.setAttribute( "metadata", true );
|
||||
|
||||
for( JournalEntryVector::const_iterator it = m_journalEntries.begin();
|
||||
it != m_journalEntries.end(); ++it )
|
||||
for( JournalCheckPointVector::const_iterator it = m_journalCheckPoints.begin();
|
||||
it != m_journalCheckPoints.end(); ++it )
|
||||
{
|
||||
QDomElement je_de = _doc.createElement( "entry" );
|
||||
je_de.setAttribute( "pos", (int)( it -
|
||||
m_journalEntries.begin() ) );
|
||||
je_de.setAttribute( "actionid", it->actionID() );
|
||||
je_de.setAttribute( "data", base64::encode( it->data() ) );
|
||||
m_journalCheckPoints.begin() ) );
|
||||
//je_de.setAttribute( "data", base64::encode( it->data().toString() ) );
|
||||
je_de.setAttribute( "data", it->data().toString() );
|
||||
journal_de.appendChild( je_de );
|
||||
}
|
||||
|
||||
@@ -213,7 +220,7 @@ void JournallingObject::loadJournal( const QDomElement & _this )
|
||||
|
||||
changeID( new_id );
|
||||
|
||||
m_journalEntries.resize( _this.attribute( "entries" ).toInt() );
|
||||
m_journalCheckPoints.resize( _this.attribute( "entries" ).toInt() );
|
||||
|
||||
QDomNode node = _this.firstChild();
|
||||
while( !node.isNull() )
|
||||
@@ -221,15 +228,14 @@ void JournallingObject::loadJournal( const QDomElement & _this )
|
||||
if( node.isElement() )
|
||||
{
|
||||
const QDomElement & je = node.toElement();
|
||||
m_journalEntries[je.attribute( "pos" ).toInt()] =
|
||||
JournalEntry(
|
||||
je.attribute( "actionid" ).toInt(),
|
||||
base64::decode( je.attribute( "data" ) ) );
|
||||
m_journalCheckPoints[je.attribute( "pos" ).toInt()] =
|
||||
JournalCheckPoint(
|
||||
multimediaProject( je.attribute( "data" ).toUtf8() ) );
|
||||
}
|
||||
node = node.nextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
m_currentJournalEntry = m_journalEntries.begin() +
|
||||
m_currentJournalCheckPoint = m_journalCheckPoints.begin() +
|
||||
_this.attribute( "curentry" ).toInt();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* ProjectJournal.cpp - implementation of ProjectJournal
|
||||
*
|
||||
* Copyright (c) 2006-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -60,7 +60,10 @@ void ProjectJournal::undo()
|
||||
if( m_currentJournalEntry - 1 >= m_journalEntries.begin() &&
|
||||
( jo = m_joIDs[*--m_currentJournalEntry] ) != NULL )
|
||||
{
|
||||
bool prev = isJournalling();
|
||||
setJournalling( false );
|
||||
jo->undo();
|
||||
setJournalling( prev );
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
}
|
||||
@@ -81,7 +84,10 @@ void ProjectJournal::redo()
|
||||
if( m_currentJournalEntry < m_journalEntries.end() &&
|
||||
( jo = m_joIDs[*m_currentJournalEntry++] ) != NULL )
|
||||
{
|
||||
bool prev = isJournalling();
|
||||
setJournalling( false );
|
||||
jo->redo();
|
||||
setJournalling( prev );
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* note.cpp - implementation of class note
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -50,8 +50,6 @@ note::note( const midiTime & _length, const midiTime & _pos,
|
||||
m_pos( _pos ),
|
||||
m_detuning( NULL )
|
||||
{
|
||||
//saveJournallingState( false );
|
||||
// setJournalling( false );
|
||||
if( _detuning )
|
||||
{
|
||||
m_detuning = sharedObject::ref( _detuning );
|
||||
@@ -60,7 +58,6 @@ note::note( const midiTime & _length, const midiTime & _pos,
|
||||
{
|
||||
createDetuning();
|
||||
}
|
||||
//restoreJournallingState();
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +103,6 @@ note::~note()
|
||||
|
||||
void note::setLength( const midiTime & _length )
|
||||
{
|
||||
// addJournalEntry( journalEntry( ChangeLength, m_length - _length ) );
|
||||
m_length = _length;
|
||||
}
|
||||
|
||||
@@ -115,7 +111,6 @@ void note::setLength( const midiTime & _length )
|
||||
|
||||
void note::setPos( const midiTime & _pos )
|
||||
{
|
||||
// addJournalEntry( journalEntry( ChangePosition, m_pos - _pos ) );
|
||||
m_pos = _pos;
|
||||
}
|
||||
|
||||
@@ -125,7 +120,6 @@ void note::setPos( const midiTime & _pos )
|
||||
void note::setKey( const int _key )
|
||||
{
|
||||
const int k = tLimit( _key, 0, NumKeys );
|
||||
// addJournalEntry( journalEntry( ChangeKey, m_key - k ) );
|
||||
m_key = k;
|
||||
}
|
||||
|
||||
@@ -135,7 +129,6 @@ void note::setKey( const int _key )
|
||||
void note::setVolume( const volume_t _volume )
|
||||
{
|
||||
const volume_t v = tLimit( _volume, MinVolume, MaxVolume );
|
||||
// addJournalEntry( journalEntry( ChangeVolume, (int) m_volume - v ) );
|
||||
m_volume = v;
|
||||
}
|
||||
|
||||
@@ -145,7 +138,6 @@ void note::setVolume( const volume_t _volume )
|
||||
void note::setPanning( const panning_t _panning )
|
||||
{
|
||||
const panning_t p = tLimit( _panning, PanningLeft, PanningRight );
|
||||
// addJournalEntry( journalEntry( ChangePanning, (int) m_panning - p ) );
|
||||
m_panning = p;
|
||||
}
|
||||
|
||||
@@ -219,46 +211,6 @@ void note::loadSettings( const QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
/*void note::undoStep( journalEntry & _je )
|
||||
{
|
||||
saveJournallingState( false );
|
||||
switch( static_cast<Actions>( _je.actionID() ) )
|
||||
{
|
||||
case ChangeKey:
|
||||
setKey( key() - _je.data().toInt() );
|
||||
break;
|
||||
|
||||
case ChangeVolume:
|
||||
setVolume( getVolume() - _je.data().toInt() );
|
||||
break;
|
||||
|
||||
case ChangePanning:
|
||||
setPanning( getPanning() - _je.data().toInt() );
|
||||
break;
|
||||
|
||||
case ChangeLength:
|
||||
setLength( length() - _je.data().toInt() );
|
||||
break;
|
||||
|
||||
case ChangePosition:
|
||||
setPos( pos() - _je.data().toInt() );
|
||||
break;
|
||||
}
|
||||
restoreJournallingState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void note::redoStep( journalEntry & _je )
|
||||
{
|
||||
journalEntry je( _je.actionID(), -_je.data().toInt() );
|
||||
undoStep( je );
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
void note::editDetuningPattern()
|
||||
{
|
||||
m_detuning->automationPattern()->openInAutomationEditor();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* track.cpp - implementation of classes concerning tracks -> necessary for
|
||||
* all track-like objects (beat/bassline, sample-track...)
|
||||
*
|
||||
* Copyright (c) 2004-2012 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -149,7 +149,6 @@ void trackContentObject::movePosition( const midiTime & _pos )
|
||||
{
|
||||
if( m_startPosition != _pos )
|
||||
{
|
||||
addJournalEntry( JournalEntry( Move, m_startPosition - _pos ) );
|
||||
m_startPosition = _pos;
|
||||
engine::getSong()->updateLength();
|
||||
}
|
||||
@@ -170,7 +169,6 @@ void trackContentObject::changeLength( const midiTime & _length )
|
||||
{
|
||||
if( m_length != _length )
|
||||
{
|
||||
addJournalEntry( JournalEntry( Resize, m_length - _length ) );
|
||||
m_length = _length;
|
||||
engine::getSong()->updateLength();
|
||||
}
|
||||
@@ -180,47 +178,6 @@ void trackContentObject::changeLength( const midiTime & _length )
|
||||
|
||||
|
||||
|
||||
/*! \brief Undo one journal entry of this trackContentObject
|
||||
*
|
||||
* Restore the previous state of this track content object. This will
|
||||
* restore the position or the length of the track content object
|
||||
* depending on what was changed.
|
||||
*
|
||||
* \param _je The journal entry to undo
|
||||
*/
|
||||
void trackContentObject::undoStep( JournalEntry & _je )
|
||||
{
|
||||
saveJournallingState( false );
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case Move:
|
||||
movePosition( startPosition() + _je.data().toInt() );
|
||||
break;
|
||||
case Resize:
|
||||
changeLength( length() + _je.data().toInt() );
|
||||
break;
|
||||
}
|
||||
restoreJournallingState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Redo one journal entry of this trackContentObject
|
||||
*
|
||||
* Undoes one 'undo' of this track content object.
|
||||
*
|
||||
* \param _je The journal entry to redo
|
||||
*/
|
||||
void trackContentObject::redoStep( JournalEntry & _je )
|
||||
{
|
||||
JournalEntry je( _je.actionID(), -_je.data().toInt() );
|
||||
undoStep( je );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Copy this trackContentObject to the clipboard.
|
||||
*
|
||||
* Copies this track content object to the clipboard.
|
||||
@@ -367,6 +324,8 @@ bool trackContentObjectView::fixedTCOs()
|
||||
*/
|
||||
bool trackContentObjectView::close()
|
||||
{
|
||||
m_trackView->getTrack()->addJournalCheckPoint();
|
||||
|
||||
m_trackView->getTrackContentWidget()->removeTCOView( this );
|
||||
return QWidget::close();
|
||||
}
|
||||
@@ -577,6 +536,8 @@ void trackContentObjectView::mousePressEvent( QMouseEvent * _me )
|
||||
/* engine::mainWindow()->isShiftPressed() == false &&*/
|
||||
fixedTCOs() == false )
|
||||
{
|
||||
m_tco->addJournalCheckPoint();
|
||||
|
||||
// move or resize
|
||||
m_tco->setJournalling( false );
|
||||
|
||||
@@ -773,9 +734,6 @@ void trackContentObjectView::mouseReleaseEvent( QMouseEvent * _me )
|
||||
if( m_action == Move || m_action == Resize )
|
||||
{
|
||||
m_tco->setJournalling( true );
|
||||
m_tco->addJournalEntry( JournalEntry( m_action, m_oldTime -
|
||||
( ( m_action == Move ) ?
|
||||
m_tco->startPosition() : m_tco->length() ) ) );
|
||||
}
|
||||
m_action = NoAction;
|
||||
delete m_hint;
|
||||
@@ -951,9 +909,6 @@ void trackContentWidget::updateBackground()
|
||||
void trackContentWidget::addTCOView( trackContentObjectView * _tcov )
|
||||
{
|
||||
trackContentObject * tco = _tcov->getTrackContentObject();
|
||||
/* QMap<QString, QVariant> map;
|
||||
map["id"] = tco->id();
|
||||
addJournalEntry( JournalEntry( AddTrackContentObject, map ) );*/
|
||||
|
||||
m_tcoViews.push_back( _tcov );
|
||||
|
||||
@@ -978,14 +933,6 @@ void trackContentWidget::removeTCOView( trackContentObjectView * _tcov )
|
||||
_tcov );
|
||||
if( it != m_tcoViews.end() )
|
||||
{
|
||||
/* QMap<QString, QVariant> map;
|
||||
multimediaProject mmp( multimediaProject::JournalData );
|
||||
_tcov->getTrackContentObject()->saveState( mmp, mmp.content() );
|
||||
map["id"] = _tcov->getTrackContentObject()->id();
|
||||
map["state"] = mmp.toString();
|
||||
addJournalEntry( JournalEntry( RemoveTrackContentObject,
|
||||
map ) );*/
|
||||
|
||||
m_tcoViews.erase( it );
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
@@ -1127,6 +1074,7 @@ void trackContentWidget::dropEvent( QDropEvent * _de )
|
||||
{
|
||||
const midiTime pos = getPosition( _de->pos().x()
|
||||
).toNearestTact();
|
||||
getTrack()->addJournalCheckPoint();
|
||||
trackContentObject * tco = getTrack()->createTCO( pos );
|
||||
|
||||
// value contains our XML-data so simply create a
|
||||
@@ -1167,6 +1115,7 @@ void trackContentWidget::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
const midiTime pos = getPosition( _me->x() ).getTact() *
|
||||
midiTime::ticksPerTact();
|
||||
getTrack()->addJournalCheckPoint();
|
||||
trackContentObject * tco = getTrack()->createTCO( pos );
|
||||
|
||||
tco->saveJournallingState( false );
|
||||
@@ -1215,71 +1164,6 @@ void trackContentWidget::resizeEvent( QResizeEvent * resizeEvent )
|
||||
|
||||
|
||||
|
||||
/*! \brief Undo an action on the trackContentWidget
|
||||
*
|
||||
* \param _je the details of the edit journal
|
||||
*/
|
||||
void trackContentWidget::undoStep( JournalEntry & _je )
|
||||
{
|
||||
saveJournallingState( false );
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case AddTrackContentObject:
|
||||
{
|
||||
QMap<QString, QVariant> map = _je.data().toMap();
|
||||
trackContentObject * tco =
|
||||
dynamic_cast<trackContentObject *>(
|
||||
engine::projectJournal()->journallingObject( map["id"].toInt() ) );
|
||||
multimediaProject mmp( multimediaProject::JournalData );
|
||||
tco->saveState( mmp, mmp.content() );
|
||||
map["state"] = mmp.toString();
|
||||
_je.data() = map;
|
||||
tco->deleteLater();
|
||||
break;
|
||||
}
|
||||
|
||||
case RemoveTrackContentObject:
|
||||
{
|
||||
trackContentObject * tco = getTrack()->createTCO( midiTime( 0 ) );
|
||||
multimediaProject mmp(
|
||||
_je.data().toMap()["state"].
|
||||
toString().toUtf8() );
|
||||
tco->restoreState( mmp.content().firstChild().toElement() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
restoreJournallingState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Redo an action of the trackContentWidget
|
||||
*
|
||||
* \param _je the entry in the edit journal to redo.
|
||||
*/
|
||||
void trackContentWidget::redoStep( JournalEntry & _je )
|
||||
{
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case AddTrackContentObject:
|
||||
case RemoveTrackContentObject:
|
||||
_je.actionID() = ( _je.actionID() ==
|
||||
AddTrackContentObject ) ?
|
||||
RemoveTrackContentObject :
|
||||
AddTrackContentObject;
|
||||
undoStep( _je );
|
||||
_je.actionID() = ( _je.actionID() ==
|
||||
AddTrackContentObject ) ?
|
||||
RemoveTrackContentObject :
|
||||
AddTrackContentObject;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Return the track shown by the trackContentWidget
|
||||
*
|
||||
*/
|
||||
@@ -2231,55 +2115,6 @@ void trackView::modelChanged()
|
||||
|
||||
|
||||
|
||||
/*! \brief Undo a change to this track View.
|
||||
*
|
||||
* \param _je the Journal Entry to undo.
|
||||
*/
|
||||
void trackView::undoStep( JournalEntry & _je )
|
||||
{
|
||||
saveJournallingState( false );
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case MoveTrack:
|
||||
if( _je.data().toInt() > 0 )
|
||||
{
|
||||
m_trackContainerView->moveTrackViewUp( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trackContainerView->moveTrackViewDown( this );
|
||||
}
|
||||
break;
|
||||
case ResizeTrack:
|
||||
setFixedHeight( qMax<int>( height() +
|
||||
_je.data().toInt(),
|
||||
MINIMAL_TRACK_HEIGHT ) );
|
||||
m_trackContainerView->realignTracks();
|
||||
break;
|
||||
/*case RestoreTrack:
|
||||
setFixedHeight( DEFAULT_TRACK_HEIGHT );
|
||||
m_trackContainerView->realignTracks();
|
||||
break; */
|
||||
}
|
||||
restoreJournallingState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Redo a change to this track View.
|
||||
*
|
||||
* \param _je the Journal Event to redo.
|
||||
*/
|
||||
void trackView::redoStep( JournalEntry & _je )
|
||||
{
|
||||
JournalEntry je( _je.actionID(), -_je.data().toInt() );
|
||||
undoStep( je );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief Start a drag event on this track View.
|
||||
*
|
||||
* \param _dee the DragEnterEvent to start.
|
||||
@@ -2414,6 +2249,7 @@ void trackView::mouseMoveEvent( QMouseEvent * _me )
|
||||
// a track-widget not equal to ourself?
|
||||
if( track_at_y != NULL && track_at_y != this )
|
||||
{
|
||||
addJournalCheckPoint();
|
||||
// then move us up/down there!
|
||||
if( _me->y() < 0 )
|
||||
{
|
||||
@@ -2423,7 +2259,6 @@ void trackView::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
m_trackContainerView->moveTrackViewDown( this );
|
||||
}
|
||||
addJournalEntry( JournalEntry( MoveTrack, _me->y() ) );
|
||||
}
|
||||
}
|
||||
else if( m_action == ResizeTrack )
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* track_container.cpp - implementation of base-class for all track-containers
|
||||
* like Song-Editor, BB-Editor...
|
||||
*
|
||||
* Copyright (c) 2004-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -73,10 +73,16 @@ void trackContainer::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
|
||||
void trackContainer::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
bool journalRestore = _this.parentNode().nodeName() == "journaldata";
|
||||
if( journalRestore )
|
||||
{
|
||||
clearAllTracks();
|
||||
}
|
||||
|
||||
static QProgressDialog * pd = NULL;
|
||||
bool was_null = ( pd == NULL );
|
||||
int start_val = 0;
|
||||
if( engine::hasGUI() )
|
||||
if( !journalRestore && engine::hasGUI() )
|
||||
{
|
||||
if( pd == NULL )
|
||||
{
|
||||
@@ -154,6 +160,8 @@ void trackContainer::addTrack( track * _track )
|
||||
{
|
||||
if( _track->type() != track::HiddenAutomationTrack )
|
||||
{
|
||||
addJournalCheckPoint();
|
||||
|
||||
m_tracksMutex.lockForWrite();
|
||||
m_tracks.push_back( _track );
|
||||
m_tracksMutex.unlock();
|
||||
|
||||
@@ -121,10 +121,6 @@ void trackContainerView::loadSettings( const QDomElement & _this )
|
||||
|
||||
trackView * trackContainerView::addTrackView( trackView * _tv )
|
||||
{
|
||||
/* QMap<QString, QVariant> map;
|
||||
map["id"] = _tv->getTrack()->id();
|
||||
addJournalEntry( JournalEntry( AddTrack, map ) );*/
|
||||
|
||||
m_trackViews.push_back( _tv );
|
||||
m_scrollLayout->addWidget( _tv );
|
||||
connect( this, SIGNAL( positionChanged( const midiTime & ) ),
|
||||
@@ -142,13 +138,6 @@ void trackContainerView::removeTrackView( trackView * _tv )
|
||||
int index = m_trackViews.indexOf( _tv );
|
||||
if( index != -1 )
|
||||
{
|
||||
/* QMap<QString, QVariant> map;
|
||||
multimediaProject mmp( multimediaProject::JournalData );
|
||||
_tv->getTrack()->saveState( mmp, mmp.content() );
|
||||
map["id"] = _tv->getTrack()->id();
|
||||
map["state"] = mmp.toString();
|
||||
addJournalEntry( JournalEntry( RemoveTrack, map ) );*/
|
||||
|
||||
m_trackViews.removeAt( index );
|
||||
|
||||
disconnect( _tv );
|
||||
@@ -238,6 +227,8 @@ void trackContainerView::createTrackView( track * _t )
|
||||
|
||||
void trackContainerView::deleteTrackView( trackView * _tv )
|
||||
{
|
||||
m_tc->addJournalCheckPoint();
|
||||
|
||||
track * t = _tv->getTrack();
|
||||
removeTrackView( _tv );
|
||||
delete _tv;
|
||||
@@ -307,64 +298,6 @@ void trackContainerView::clearAllTracks()
|
||||
|
||||
|
||||
|
||||
void trackContainerView::undoStep( JournalEntry & _je )
|
||||
{
|
||||
#if 0
|
||||
saveJournallingState( false );
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case AddTrack:
|
||||
{
|
||||
QMap<QString, QVariant> map = _je.data().toMap();
|
||||
track * t =
|
||||
dynamic_cast<track *>(
|
||||
engine::projectJournal()->getJournallingObject(
|
||||
map["id"].toInt() ) );
|
||||
assert( t != NULL );
|
||||
multimediaProject mmp( multimediaProject::JournalData );
|
||||
t->saveState( mmp, mmp.content() );
|
||||
map["state"] = mmp.toString();
|
||||
_je.data() = map;
|
||||
t->deleteLater();
|
||||
break;
|
||||
}
|
||||
|
||||
case RemoveTrack:
|
||||
{
|
||||
multimediaProject mmp(
|
||||
_je.data().toMap()["state"].toString().utf8() );
|
||||
track::create( mmp.content().firstChild().toElement(),
|
||||
m_tc );
|
||||
break;
|
||||
}
|
||||
}
|
||||
restoreJournallingState();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainerView::redoStep( JournalEntry & _je )
|
||||
{
|
||||
#if 0
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case AddTrack:
|
||||
case RemoveTrack:
|
||||
_je.actionID() = ( _je.actionID() == AddTrack ) ?
|
||||
RemoveTrack : AddTrack;
|
||||
undoStep( _je );
|
||||
_je.actionID() = ( _je.actionID() == AddTrack ) ?
|
||||
RemoveTrack : AddTrack;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainerView::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
{
|
||||
stringPairDrag::processDragEnterEvent( _dee,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* knob.cpp - powerful knob-widget
|
||||
*
|
||||
* Copyright (c) 2004-2011 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -438,7 +438,12 @@ void knob::mousePressEvent( QMouseEvent * _me )
|
||||
! ( _me->modifiers() & Qt::ControlModifier ) &&
|
||||
! ( _me->modifiers() & Qt::ShiftModifier ) )
|
||||
{
|
||||
model()->prepareJournalEntryFromOldVal();
|
||||
AutomatableModel *thisModel = model();
|
||||
if( thisModel )
|
||||
{
|
||||
thisModel->addJournalCheckPoint();
|
||||
thisModel->saveJournallingState( false );
|
||||
}
|
||||
|
||||
const QPoint & p = _me->pos();
|
||||
m_origMousePos = p;
|
||||
@@ -485,7 +490,7 @@ void knob::mouseMoveEvent( QMouseEvent * _me )
|
||||
|
||||
void knob::mouseReleaseEvent( QMouseEvent * /* _me*/ )
|
||||
{
|
||||
model()->addJournalEntryFromOldToCurVal();
|
||||
model()->restoreJournallingState();
|
||||
|
||||
m_buttonPressed = false;
|
||||
|
||||
|
||||
@@ -100,7 +100,13 @@ void lcdSpinBox::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
m_origMousePos = event->globalPos();
|
||||
QApplication::setOverrideCursor( Qt::BlankCursor );
|
||||
model()->prepareJournalEntryFromOldVal();
|
||||
|
||||
AutomatableModel *thisModel = model();
|
||||
if( thisModel )
|
||||
{
|
||||
thisModel->addJournalCheckPoint();
|
||||
thisModel->saveJournallingState( false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -131,7 +137,12 @@ void lcdSpinBox::mouseMoveEvent( QMouseEvent* event )
|
||||
|
||||
void lcdSpinBox::mouseReleaseEvent( QMouseEvent* event )
|
||||
{
|
||||
model()->addJournalEntryFromOldToCurVal();
|
||||
AutomatableModel *thisModel = model();
|
||||
if( thisModel )
|
||||
{
|
||||
thisModel->restoreJournallingState();
|
||||
}
|
||||
|
||||
|
||||
QCursor::setPos( m_origMousePos );
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
Reference in New Issue
Block a user