diff --git a/ChangeLog b/ChangeLog index 36b801057..c84dc7944 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ 2006-03-14 Tobias Doerffel + * include/types.h: + added type for editable-object-ID + + * include/track.h: + * src/core/track.cpp: + * src/tracks/bb_track.cpp: + * src/tracks/pattern.cpp: + * src/tracks/sample_track.cpp: + undo/redo-support for position- and size-changes of TCO + + * include/automatable_object.h: + added methods for saving step-recording-state on stack and restoring + it + * include/automatable_object.h: * include/automatable_button.h: * include/knob.h: diff --git a/TODO b/TODO index 7386239a1..854e0b4ab 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,5 @@ +- implement editableSettingsObject +- unique id's for all editable objects - add edit-history to project for making it possible to undo things even if you did them in a previous session - make edit-history qobject and undo/redo slots -> direct connection to GUI - restore stacking-order of windows when loading project diff --git a/configure.in b/configure.in index f35f320ee..4edf20c08 100644 --- a/configure.in +++ b/configure.in @@ -2,8 +2,8 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) -AC_INIT(lmms, 0.1.4-cvs20060313, tobydox/at/users/dot/sourceforge/dot/net) -AM_INIT_AUTOMAKE(lmms, 0.1.4-cvs20060313) +AC_INIT(lmms, 0.1.4-cvs20060314, tobydox/at/users/dot/sourceforge/dot/net) +AM_INIT_AUTOMAKE(lmms, 0.1.4-cvs20060314) AM_CONFIG_HEADER(config.h) diff --git a/include/automatable_object.h b/include/automatable_object.h index 2b54c3dfc..9833e500d 100755 --- a/include/automatable_object.h +++ b/include/automatable_object.h @@ -127,10 +127,9 @@ public: inline virtual void setInitValue( const T _value ) { - const bool sr = isRecordingSteps(); - setStepRecording( FALSE ); + saveStepRecordingState( FALSE ); setValue( _value ); - setStepRecording( sr ); + restoreStepRecordingState(); } inline virtual void setValue( const T _value ) @@ -159,11 +158,10 @@ public: it->fittedValue( value() ) != it->value() ) { - const bool sr = it->isRecordingSteps(); - it->setStepRecording( + it->saveStepRecordingState( isRecordingSteps() ); it->setValue( value() ); - it->setStepRecording( sr ); + it->restoreStepRecordingState(); } } } @@ -244,8 +242,7 @@ public: protected: virtual void redoStep( const editStep & _edit_step ) { - const bool sr = isRecordingSteps(); - setStepRecording( FALSE ); + saveStepRecordingState( FALSE ); #ifndef QT3 setValue( static_cast( value() + _edit_step.data().value() ) ); @@ -253,7 +250,7 @@ protected: setValue( static_cast( value() + static_cast( _edit_step.data().toDouble() ) ) ); #endif - setStepRecording( sr ); + restoreStepRecordingState(); } virtual void undoStep( const editStep & _edit_step ) diff --git a/include/qt3support.h b/include/qt3support.h index 5d0701110..a46c36085 100644 --- a/include/qt3support.h +++ b/include/qt3support.h @@ -57,8 +57,10 @@ class QColorGroup; typedef int csize; #define QListViewItem Q3ListViewItem -#define vvector QVector + #define vlist QList +#define vstack QStack +#define vvector QVector #include @@ -72,8 +74,10 @@ inline QString baseName( const QString & _file ) #else /* QT3 */ -#define vvector QValueVector #define vlist QValueList +#define vstack QValueStack +#define vvector QValueVector + #define QMenu QPopupMenu #define QAbstractButton QButton diff --git a/include/track.h b/include/track.h index d0ef77eb1..254b2bf10 100644 --- a/include/track.h +++ b/include/track.h @@ -57,6 +57,7 @@ #include "settings.h" #include "rubberband.h" #include "engine.h" +#include "editable_object.h" class QMenu; @@ -79,7 +80,7 @@ const Uint16 TCO_BORDER_WIDTH = 1; class trackContentObject : public selectableObject, public settings, - public engineObject + public editableObject { Q_OBJECT public: @@ -129,6 +130,9 @@ protected: void setAutoResizeEnabled( bool _e = FALSE ); float pixelsPerTact( void ); + virtual void undoStep( const editStep & _edit_step ); + virtual void redoStep( const editStep & _edit_step ); + protected slots: void cut( void ); @@ -153,12 +157,14 @@ private: textFloat * m_hint; + midiTime m_oldTime;// used for undo/redo while mouse-button is pressed + } ; -class trackContentWidget : public QWidget +class trackContentWidget : public QWidget, public editableObject { Q_OBJECT public: @@ -200,8 +206,16 @@ protected: virtual void paintEvent( QPaintEvent * _pe ); virtual void resizeEvent( QResizeEvent * _re ); + virtual void undoStep( const editStep & _edit_step ); + virtual void redoStep( const editStep & _edit_step ); + private: + enum actions + { + ADD_TCO, REMOVE_TCO + } ; + track * getTrack( void ); midiTime getPosition( int _mouse_x ); diff --git a/include/types.h b/include/types.h index 9b792ee6e..5f7552a0b 100644 --- a/include/types.h +++ b/include/types.h @@ -54,4 +54,6 @@ typedef Uint16 bpm_t; // tempo (MIN_BPM to MAX_BPM) typedef Uint16 bitrate_t; // bitrate in kbps typedef Sint8 fx_ch_t; // FX-channel (0 to MAX_EFFECT_CHANNEL) +typedef Uint32 eo_id_t; // (unique) ID of an editable object + #endif diff --git a/src/core/track.cpp b/src/core/track.cpp index fb4d0de6d..83783b0c3 100644 --- a/src/core/track.cpp +++ b/src/core/track.cpp @@ -88,7 +88,8 @@ trackContentObject::trackContentObject( track * _track ) : , Qt::WDestructiveClose #endif ), - engineObject( _track->eng() ), + settings(), + editableObject( _track->eng() ), m_track( _track ), m_startPosition(), m_length(), @@ -110,8 +111,11 @@ trackContentObject::trackContentObject( track * _track ) : setFocusPolicy( StrongFocus ); #endif show(); + + setStepRecording( FALSE ); movePosition( 0 ); changeLength( 0 ); + setStepRecording( TRUE ); setFixedHeight( parentWidget()->height() - 2 ); setAcceptDrops( TRUE ); @@ -141,9 +145,10 @@ void trackContentObject::movePosition( const midiTime & _pos ) { if( m_startPosition != _pos ) { - getTrack()->eng()->getSongEditor()->setModified(); + //getTrack()->eng()->getSongEditor()->setModified(); + addStep( editStep( MOVE, m_startPosition - _pos ) ); + m_startPosition = _pos; } - m_startPosition = _pos; m_track->getTrackWidget()->changePosition(); // moving a TCO can result in change of song-length etc., // therefore we update the track-container @@ -157,34 +162,20 @@ void trackContentObject::changeLength( const midiTime & _length ) { if( m_length != _length ) { - getTrack()->eng()->getSongEditor()->setModified(); + //getTrack()->eng()->getSongEditor()->setModified(); + addStep( editStep( RESIZE, m_length - _length ) ); + m_length = _length; } - m_length = _length; - setFixedWidth( static_cast( m_length * pixelsPerTact() / 64 ) + - TCO_BORDER_WIDTH * 2 ); + setFixedWidth( static_cast( m_length * pixelsPerTact() / + 64 ) + TCO_BORDER_WIDTH * 2 ); // changing length of TCO can result in change of song-length etc., - // therefore we update the trackcontainer + // therefore we update the track-container m_track->getTrackContainer()->update(); } -float trackContentObject::pixelsPerTact( void ) -{ - if( fixedTCOs() ) - { - return( ( getTrack()->getTrackContentWidget()->width() - - 2 * TCO_BORDER_WIDTH - - DEFAULT_SCROLLBAR_SIZE ) / - tMax( length().getTact(), 1.0f ) ); - } - return( getTrack()->getTrackContainer()->pixelsPerTact() ); -} - - - - void trackContentObject::dragEnterEvent( QDragEnterEvent * _dee ) { stringPairDrag::processDragEnterEvent( _dee, "tco_" + @@ -283,11 +274,14 @@ void trackContentObject::mousePressEvent( QMouseEvent * _me ) /* eng()->getMainWindow()->isShiftPressed() == FALSE &&*/ fixedTCOs() == FALSE ) { + setStepRecording( FALSE ); + m_initialMouseX = _me->x(); - + if( _me->x() < width() - RESIZE_GRIP_WIDTH ) { m_action = MOVE; + m_oldTime = m_startPosition; QCursor c( Qt::SizeAllCursor ); QApplication::setOverrideCursor( c ); s_textFloat->setTitle( tr( "Current position" ) ); @@ -300,6 +294,7 @@ void trackContentObject::mousePressEvent( QMouseEvent * _me ) else if( m_autoResize == FALSE ) { m_action = RESIZE; + m_oldTime = m_length; QCursor c( Qt::SizeHorCursor ); QApplication::setOverrideCursor( c ); s_textFloat->setTitle( tr( "Current length" ) ); @@ -434,6 +429,13 @@ void trackContentObject::mouseMoveEvent( QMouseEvent * _me ) void trackContentObject::mouseReleaseEvent( QMouseEvent * _me ) { + if( m_action == MOVE || m_action == RESIZE ) + { + setStepRecording( TRUE ); + addStep( editStep( m_action, m_oldTime - + ( ( m_action == MOVE ) ? + m_startPosition : m_length ) ) ); + } m_action = NONE; delete m_hint; m_hint = NULL; @@ -476,6 +478,49 @@ void trackContentObject::contextMenuEvent( QContextMenuEvent * _cme ) +float trackContentObject::pixelsPerTact( void ) +{ + if( fixedTCOs() ) + { + return( ( getTrack()->getTrackContentWidget()->width() - + 2 * TCO_BORDER_WIDTH - + DEFAULT_SCROLLBAR_SIZE ) / + tMax( length().getTact(), 1.0f ) ); + } + return( getTrack()->getTrackContainer()->pixelsPerTact() ); +} + + + + +void trackContentObject::undoStep( const editStep & _edit_step ) +{ + saveStepRecordingState( FALSE ); + switch( _edit_step.actionID() ) + { + case MOVE: + movePosition( startPosition() + + _edit_step.data().toInt() ); + break; + case RESIZE: + changeLength( length() + _edit_step.data().toInt() ); + break; + } + restoreStepRecordingState(); +} + + + + +void trackContentObject::redoStep( const editStep & _edit_step ) +{ + undoStep( editStep( _edit_step.actionID(), + -_edit_step.data().toInt() ) ); +} + + + + void trackContentObject::close( void ) { m_track->getTrackContentWidget()->removeTCO( this, FALSE ); @@ -531,6 +576,7 @@ void trackContentObject::setAutoResizeEnabled( bool _e ) // =========================================================================== trackContentWidget::trackContentWidget( trackWidget * _parent ) : QWidget( _parent ), + editableObject( _parent->getTrack()->eng() ), m_trackWidget( _parent ) { #ifdef QT4 @@ -579,9 +625,14 @@ csize trackContentWidget::numOfTCOs( void ) trackContentObject * FASTCALL trackContentWidget::addTCO( trackContentObject * _tco ) { + //addStep( editStep( ADD_TCO, 0 ) ); m_trackContentObjects.push_back( _tco ); _tco->move( 0, 1 ); + + _tco->saveStepRecordingState( FALSE ); m_trackWidget->changePosition(); + _tco->restoreStepRecordingState(); + getTrack()->eng()->getSongEditor()->setModified(); return( _tco ); // just for convenience } @@ -605,6 +656,7 @@ void trackContentWidget::removeTCO( trackContentObject * _tco, _tco ); if( it != m_trackContentObjects.end() ) { + //addStep( editStep( REMOVE_TCO, 0 ) ); if( _also_delete ) { delete _tco; @@ -757,10 +809,12 @@ void trackContentWidget::mousePressEvent( QMouseEvent * _me ) else if( _me->button() == Qt::LeftButton && getTrack()->getTrackContainer()->fixedTCOs() == FALSE ) { - const midiTime pos = getPosition( _me->x() ).toNearestTact(); + const midiTime pos = getPosition( _me->x() ).getTact() * 64; trackContentObject * tco = addTCO( getTrack()->createTCO( pos ) ); + tco->saveStepRecordingState( FALSE ); tco->movePosition( pos ); + tco->restoreStepRecordingState(); } } @@ -807,6 +861,31 @@ void trackContentWidget::resizeEvent( QResizeEvent * _re ) +void trackContentWidget::undoStep( const editStep & _edit_step ) +{ + saveStepRecordingState( FALSE ); + switch( _edit_step.actionID() ) + { + case ADD_TCO: + break; + case REMOVE_TCO: + break; + } + restoreStepRecordingState(); +} + + + + +void trackContentWidget::redoStep( const editStep & _edit_step ) +{ +/* undoStep( editStep( _edit_step.actionID(), + -_edit_step.data().toInt() ) );*/ +} + + + + track * trackContentWidget::getTrack( void ) { return( m_trackWidget->getTrack() ); diff --git a/src/tracks/bb_track.cpp b/src/tracks/bb_track.cpp index 15433a94c..a6054eff6 100644 --- a/src/tracks/bb_track.cpp +++ b/src/tracks/bb_track.cpp @@ -72,7 +72,9 @@ bbTCO::bbTCO( track * _track, const QColor & _c ) : bbTrack::numOfBBTrack( getTrack() ) ); if( t > 0 ) { + saveStepRecordingState( FALSE ); changeLength( midiTime( t, 0 ) ); + restoreStepRecordingState(); } } diff --git a/src/tracks/pattern.cpp b/src/tracks/pattern.cpp index ab4c95252..4a0736611 100644 --- a/src/tracks/pattern.cpp +++ b/src/tracks/pattern.cpp @@ -186,9 +186,12 @@ void pattern::init( void ) s_frozen = new QPixmap( embed::getIconPixmap( "frozen" ) ); } + saveStepRecordingState( FALSE ); + ensureBeatNotes(); changeLength( length() ); + restoreStepRecordingState(); #ifndef QT4 // set background-mode for flicker-free redraw diff --git a/src/tracks/sample_track.cpp b/src/tracks/sample_track.cpp index 360bd0921..baf155aaf 100644 --- a/src/tracks/sample_track.cpp +++ b/src/tracks/sample_track.cpp @@ -64,7 +64,9 @@ sampleTCO::sampleTCO( track * _track ) : setBackgroundMode( Qt::NoBackground ); #endif + saveStepRecordingState( FALSE ); setSampleFile( "" ); + restoreStepRecordingState(); // we need to receive bpm-change-events, because then we have to // change length of this TCO