From a5c3cf6a99fbe1b471e64b7aecb0bcb3cf3454aa Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Tue, 7 Jan 2014 23:42:17 +0100 Subject: [PATCH] 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. --- include/AutomatableModel.h | 22 ++-- include/JournallingObject.h | 67 ++++-------- include/note.h | 15 +-- include/surround_area.h | 14 +-- include/track.h | 18 +-- include/track_container_view.h | 5 +- src/core/AutomatableModel.cpp | 67 +++--------- src/core/JournallingObject.cpp | 66 ++++++----- src/core/ProjectJournal.cpp | 8 +- src/core/note.cpp | 50 +-------- src/core/track.cpp | 181 ++----------------------------- src/core/track_container.cpp | 12 +- src/gui/track_container_view.cpp | 71 +----------- src/gui/widgets/knob.cpp | 11 +- src/gui/widgets/lcd_spinbox.cpp | 15 ++- 15 files changed, 134 insertions(+), 488 deletions(-) diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 453949b73..9488e8511 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -1,7 +1,7 @@ /* * AutomatableModel.h - declaration of class AutomatableModel * - * Copyright (c) 2007-2009 Tobias Doerffel + * Copyright (c) 2007-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -180,23 +180,19 @@ public: static void unlinkModels( AutomatableModel * _m1, AutomatableModel * _m2 ); - virtual void saveSettings( QDomDocument & _doc, - QDomElement & _this, - const QString & _name = QString( "value" ) ); + virtual void saveSettings( QDomDocument &doc, QDomElement &_this ); + virtual void loadSettings( const QDomElement &_this ); - virtual void loadSettings( const QDomElement & _this, - const QString & _name = QString( "value" ) ); + virtual void saveSettings( QDomDocument &doc, + QDomElement &_this, + const QString &name ); + virtual void loadSettings( const QDomElement &_this, const QString &name ); virtual QString nodeName() const { return "automatablemodel"; } - void prepareJournalEntryFromOldVal(); - - void addJournalEntryFromOldToCurVal(); - - QString displayValue( const float _val ) const { switch( m_dataType ) @@ -217,9 +213,6 @@ public slots: protected: - virtual void redoStep( JournalEntry & _je ); - virtual void undoStep( JournalEntry & _je ); - float fittedValue( float _value ) const; @@ -239,7 +232,6 @@ private: // most objects will need this temporarily (until sampleExact is // standard) float m_oldValue; - bool m_journalEntryReady; int m_setValueDepth; AutoModelVector m_linkedModels; diff --git a/include/JournallingObject.h b/include/JournallingObject.h index df9902546..84731c07c 100644 --- a/include/JournallingObject.h +++ b/include/JournallingObject.h @@ -1,7 +1,7 @@ /* * JournallingObject.h - declaration of class JournallingObject * - * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2006-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -27,6 +27,7 @@ #include "lmms_basics.h" #include "export.h" +#include "mmp.h" #include "SerializingObject.h" #include @@ -34,57 +35,37 @@ #include -typedef uint32_t t_action_id; - - -class JournalEntry +class JournalCheckPoint { public: - JournalEntry( const t_action_id _action_id, const QVariant & _data ) : - m_actionID( _action_id ), - m_data( _data ) + JournalCheckPoint( const multimediaProject &data = + multimediaProject( multimediaProject::JournalData ) ) : + m_data( data ) { } - JournalEntry() : - m_actionID( 0 ), - m_data( 0 ) + ~JournalCheckPoint() { } - ~JournalEntry() - { - } - - t_action_id actionID() const - { - return m_actionID; - } - - t_action_id & actionID() - { - return m_actionID; - } - - const QVariant & data() const + const multimediaProject &data() const { return m_data; } - QVariant & data() + multimediaProject &data() { return m_data; } private: - t_action_id m_actionID; - QVariant m_data; + multimediaProject m_data; } ; -typedef QVector JournalEntryVector; +typedef QVector JournalCheckPointVector; class EXPORT JournallingObject : public SerializingObject @@ -103,15 +84,15 @@ public: void clear() { - m_journalEntries.clear(); - m_currentJournalEntry = m_journalEntries.end(); + m_journalCheckPoints.clear(); + m_currentJournalCheckPoint = m_journalCheckPoints.end(); } void clearRedoSteps() { - m_journalEntries.erase( m_currentJournalEntry, - m_journalEntries.end() ); - m_currentJournalEntry = m_journalEntries.end(); + m_journalCheckPoints.erase( m_currentJournalCheckPoint, + m_journalCheckPoints.end() ); + m_currentJournalCheckPoint = m_journalCheckPoints.end(); } @@ -126,6 +107,8 @@ public: m_journalling = m_journallingStateStack.pop(); } + void addJournalCheckPoint(); + virtual QDomElement saveState( QDomDocument & _doc, QDomElement & _parent ); @@ -153,16 +136,6 @@ public: protected: void changeID( jo_id_t _id ); - void addJournalEntry( const JournalEntry & _je ); - - // to be implemented by sub-objects - virtual void undoStep( JournalEntry & ) - { - } - virtual void redoStep( JournalEntry & ) - { - } - private: void saveJournal( QDomDocument & _doc, QDomElement & _parent ); @@ -171,8 +144,8 @@ private: jo_id_t m_id; - JournalEntryVector m_journalEntries; - JournalEntryVector::Iterator m_currentJournalEntry; + JournalCheckPointVector m_journalCheckPoints; + JournalCheckPointVector::Iterator m_currentJournalCheckPoint; bool m_journalling; diff --git a/include/note.h b/include/note.h index 36bf1640d..11d2e4a17 100644 --- a/include/note.h +++ b/include/note.h @@ -2,7 +2,7 @@ * note.h - declaration of class note which contains all informations about a * note + definitions of several constants and enums * - * Copyright (c) 2004-2010 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -208,21 +208,8 @@ protected: QDomElement & _parent ); virtual void loadSettings( const QDomElement & _this ); -/* virtual void undoStep( JournalEntry & _je ); - virtual void redoStep( JournalEntry & _je );*/ - private: -/* enum Actions - { - ChangeKey, - ChangeVolume, - ChangePanning, - ChangeLength, - ChangePosition - } ;*/ - - // for piano roll editing bool m_selected; int m_oldKey; diff --git a/include/surround_area.h b/include/surround_area.h index 16b5822e1..30969a93a 100644 --- a/include/surround_area.h +++ b/include/surround_area.h @@ -3,7 +3,7 @@ * position of a channel + calculation of volume for each * speaker * - * Copyright (c) 2004-2008 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -57,18 +57,6 @@ public: void loadSettings( const QDomElement & _this, const QString & _name = "surpos" ); - inline void prepareJournalEntryFromOldVal() - { - m_posX.prepareJournalEntryFromOldVal(); - m_posY.prepareJournalEntryFromOldVal(); - } - - inline void addJournalEntryFromOldToCurVal() - { - m_posX.addJournalEntryFromOldToCurVal(); - m_posY.addJournalEntryFromOldToCurVal(); - } - // AutomationPattern * automationPatternX(); // AutomationPattern * automationPatternY(); diff --git a/include/track.h b/include/track.h index 1011c245d..2d7349be4 100644 --- a/include/track.h +++ b/include/track.h @@ -2,7 +2,7 @@ * track.h - declaration of classes concerning tracks -> necessary for all * track-like objects (beat/bassline, sample-track...) * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -128,11 +128,6 @@ public slots: void toggleMute(); -protected: - virtual void undoStep( JournalEntry & _je ); - virtual void redoStep( JournalEntry & _je ); - - signals: void lengthChanged(); void positionChanged(); @@ -275,17 +270,8 @@ protected: return "trackcontentwidget"; } - virtual void undoStep( JournalEntry & _je ); - virtual void redoStep( JournalEntry & _je ); - private: - enum Actions - { - AddTrackContentObject, - RemoveTrackContentObject - } ; - track * getTrack(); midiTime getPosition( int _mouse_x ); @@ -539,8 +525,6 @@ public slots: protected: virtual void modelChanged(); - virtual void undoStep( JournalEntry & _je ); - virtual void redoStep( JournalEntry & _je ); virtual QString nodeName() const { diff --git a/include/track_container_view.h b/include/track_container_view.h index cace6bf8e..6597a39ac 100644 --- a/include/track_container_view.h +++ b/include/track_container_view.h @@ -1,7 +1,7 @@ /* * track_container_view.h - view-component for trackContainer * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -139,9 +139,6 @@ protected: virtual void mouseReleaseEvent( QMouseEvent * _me ); virtual void resizeEvent( QResizeEvent * ); - virtual void undoStep( JournalEntry & _je ); - virtual void redoStep( JournalEntry & _je ); - midiTime m_currentPosition; diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index 034be3bb5..29ee3cb12 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -1,7 +1,7 @@ /* * AutomatableModel.cpp - some implementations of AutomatableModel-class * - * Copyright (c) 2008-2012 Tobias Doerffel + * Copyright (c) 2008-2014 Tobias Doerffel * * 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) _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(); - saveJournallingState( false ); - m_journalEntryReady = true; -} - - - - -void AutomatableModel::addJournalEntryFromOldToCurVal() -{ - if( m_journalEntryReady ) - { - restoreJournallingState(); - if( value() != m_oldValue ) - { - addJournalEntry( JournalEntry( 0, value() - - m_oldValue ) ); - } - m_journalEntryReady = false; - } -} - - - - void AutomatableModel::linkModel( AutomatableModel * _model ) { if( !m_linkedModels.contains( _model ) ) diff --git a/src/core/JournallingObject.cpp b/src/core/JournallingObject.cpp index b2a4bc575..7d3229597 100644 --- a/src/core/JournallingObject.cpp +++ b/src/core/JournallingObject.cpp @@ -1,7 +1,7 @@ /* * JournallingObject.cpp - implementation of journalling-object related stuff * - * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2006-2014 Tobias Doerffel * * 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(); } diff --git a/src/core/ProjectJournal.cpp b/src/core/ProjectJournal.cpp index dffd60eee..04e452fde 100644 --- a/src/core/ProjectJournal.cpp +++ b/src/core/ProjectJournal.cpp @@ -1,7 +1,7 @@ /* * ProjectJournal.cpp - implementation of ProjectJournal * - * Copyright (c) 2006-2009 Tobias Doerffel + * Copyright (c) 2006-2014 Tobias Doerffel * * 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(); } } diff --git a/src/core/note.cpp b/src/core/note.cpp index 2088e1188..e40d5f59f 100644 --- a/src/core/note.cpp +++ b/src/core/note.cpp @@ -1,7 +1,7 @@ /* * note.cpp - implementation of class note * - * Copyright (c) 2004-2009 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * 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( _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(); diff --git a/src/core/track.cpp b/src/core/track.cpp index 82694aaf5..f24ec6d0f 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -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 + * Copyright (c) 2004-2014 Tobias Doerffel * * 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 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 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 map = _je.data().toMap(); - trackContentObject * tco = - dynamic_cast( - 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( 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 ) diff --git a/src/core/track_container.cpp b/src/core/track_container.cpp index d9266f448..e366c42e2 100644 --- a/src/core/track_container.cpp +++ b/src/core/track_container.cpp @@ -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 + * Copyright (c) 2004-2014 Tobias Doerffel * * 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(); diff --git a/src/gui/track_container_view.cpp b/src/gui/track_container_view.cpp index d9da9e471..77f1305a4 100644 --- a/src/gui/track_container_view.cpp +++ b/src/gui/track_container_view.cpp @@ -121,10 +121,6 @@ void trackContainerView::loadSettings( const QDomElement & _this ) trackView * trackContainerView::addTrackView( trackView * _tv ) { -/* QMap 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 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 map = _je.data().toMap(); - track * t = - dynamic_cast( - 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, diff --git a/src/gui/widgets/knob.cpp b/src/gui/widgets/knob.cpp index efb4b6e0b..9f6840349 100644 --- a/src/gui/widgets/knob.cpp +++ b/src/gui/widgets/knob.cpp @@ -1,7 +1,7 @@ /* * knob.cpp - powerful knob-widget * - * Copyright (c) 2004-2011 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * 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; diff --git a/src/gui/widgets/lcd_spinbox.cpp b/src/gui/widgets/lcd_spinbox.cpp index dcc1ebd09..b3b27ce06 100644 --- a/src/gui/widgets/lcd_spinbox.cpp +++ b/src/gui/widgets/lcd_spinbox.cpp @@ -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();