undo/redo-support for track-content-objects
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@106 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
14
ChangeLog
14
ChangeLog
@@ -1,5 +1,19 @@
|
||||
2006-03-14 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
|
||||
|
||||
* 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:
|
||||
|
||||
2
TODO
2
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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<T>( value() +
|
||||
_edit_step.data().value<EDIT_STEP_TYPE>() ) );
|
||||
@@ -253,7 +250,7 @@ protected:
|
||||
setValue( static_cast<T>( value() + static_cast<EDIT_STEP_TYPE>(
|
||||
_edit_step.data().toDouble() ) ) );
|
||||
#endif
|
||||
setStepRecording( sr );
|
||||
restoreStepRecordingState();
|
||||
}
|
||||
|
||||
virtual void undoStep( const editStep & _edit_step )
|
||||
|
||||
@@ -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 <QFileInfo>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<int>( m_length * pixelsPerTact() / 64 ) +
|
||||
TCO_BORDER_WIDTH * 2 );
|
||||
setFixedWidth( static_cast<int>( 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<float>( 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<float>( 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() );
|
||||
|
||||
@@ -72,7 +72,9 @@ bbTCO::bbTCO( track * _track, const QColor & _c ) :
|
||||
bbTrack::numOfBBTrack( getTrack() ) );
|
||||
if( t > 0 )
|
||||
{
|
||||
saveStepRecordingState( FALSE );
|
||||
changeLength( midiTime( t, 0 ) );
|
||||
restoreStepRecordingState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user