added undo/redo-system and other features

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@104 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2006-03-14 13:30:28 +00:00
parent a6d0f95bb4
commit fe9d017e02
63 changed files with 2402 additions and 2476 deletions

View File

@@ -50,13 +50,12 @@
class QPixmap;
class automatableButtonGroup;
class channelTrack;
class comboBox;
class groupBox;
class knob;
class ledCheckBox;
class notePlayHandle;
class pixmapButton;
class tempoSyncKnob;
@@ -98,14 +97,6 @@ public:
}
protected slots:
void arpUpToggled( bool );
void arpDownToggled( bool );
void arpUpAndDownToggled( bool );
void arpRandomToggled( bool );
private:
enum arpDirections
@@ -115,7 +106,7 @@ private:
DOWN,
UP_AND_DOWN,
RANDOM
} m_arpDirection;
} ;
enum arpModes
{
@@ -137,10 +128,7 @@ private:
knob * m_arpGateKnob;
QLabel * m_arpDirectionLbl;
pixmapButton * m_arpUpBtn;
pixmapButton * m_arpDownBtn;
pixmapButton * m_arpUpAndDownBtn;
pixmapButton * m_arpRandomBtn;
automatableButtonGroup * m_arpDirectionBtnGrp;
comboBox * m_arpModeComboBox;

120
include/automatable_button.h Executable file
View File

@@ -0,0 +1,120 @@
/*
* automatable_button.h - class automatableButton, the base for all buttons
*
* Copyright (c) 2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#ifndef _AUTOMATABLE_BUTTON_H
#define _AUTOMATABLE_BUTTON_H
#include "qt3support.h"
#ifdef QT4
#include <QWidget>
#else
#include <qwidget.h>
#endif
#include "automatable_object.h"
class automatableButtonGroup;
class automatableButton : public QWidget, public automatableObject<bool>
{
Q_OBJECT
public:
automatableButton( QWidget * _parent, engine * _engine );
virtual ~automatableButton();
inline virtual bool isChecked( void ) const
{
return( value() );
}
inline void setToggleButton( bool _on )
{
m_toggleButton = _on;
setStepRecording( m_toggleButton );
}
public slots:
virtual void toggle( void );
virtual void setChecked( bool _on );
protected:
virtual void mousePressEvent( QMouseEvent * _me );
virtual void mouseReleaseEvent( QMouseEvent * _me );
private:
automatableButtonGroup * m_group;
bool m_toggleButton;
friend class automatableButtonGroup;
signals:
void clicked( void );
void toggled( bool );
} ;
class automatableButtonGroup : public QObject, public automatableObject<int>
{
Q_OBJECT
public:
automatableButtonGroup( QObject * _parent, engine * _engine );
virtual ~automatableButtonGroup();
void addButton( automatableButton * _btn );
void removeButton( automatableButton * _btn );
void activateButton( automatableButton * _btn );
virtual void setValue( const int _value );
private:
vlist<automatableButton *> m_buttons;
signals:
void valueChanged( int );
} ;
#endif

View File

@@ -28,14 +28,19 @@
#include <math.h>
#include "editable_object.h"
#include "templates.h"
template<typename T>
class automatableObject
class automatableObject : public editableObject
{
public:
automatableObject( const T _val = 0, const T _min = 0,
const T _max = 0, const T _step = 1 ) :
automatableObject( engine * _engine, const T _val = 0, const T _min = 0,
const T _max = 0,
const T _step = defaultRelStep() ) :
editableObject( _engine ),
m_oldValue( _val ),
m_value( _val ),
m_minValue( _min ),
m_maxValue( _max ),
@@ -45,6 +50,11 @@ public:
virtual ~automatableObject()
{
while( m_linkedObjects.empty() == FALSE )
{
m_linkedObjects.last()->unlinkObject( this );
m_linkedObjects.erase( m_linkedObjects.end() - 1 );
}
}
static inline T minRelStep( void )
@@ -83,31 +93,71 @@ public:
return( m_step );
}
inline virtual void setValue( const T _value )
inline T fittedValue( T _value )
{
m_value = tLimit<T>( _value, minValue(), maxValue() );
_value = tLimit<T>( _value, minValue(), maxValue() );
if( m_step != 0 )
{
m_value = static_cast<T>( floorf( m_value / m_step ) *
m_step );
_value = static_cast<T>( floorf( _value / step() ) *
step() );
}
else
{
m_value = m_minValue;
_value = minValue();
}
// correct rounding error at the border
if( tAbs<T>( m_value - m_maxValue ) < minEps() *
tAbs<T>( m_step ) )
if( tAbs<T>( _value - maxValue() ) < minEps() *
tAbs<T>( step() ) )
{
m_value = m_maxValue;
_value = maxValue();
}
// correct rounding error if value = 0
if( tAbs<T>( m_value ) < minEps() * tAbs<T>( m_step ) )
if( tAbs<T>( _value ) < minEps() * tAbs<T>( step() ) )
{
m_value = 0;
_value = 0;
}
return( _value );
}
inline virtual void setInitValue( const T _value )
{
const bool sr = isRecordingSteps();
setStepRecording( FALSE );
setValue( _value );
setStepRecording( sr );
}
inline virtual void setValue( const T _value )
{
const T old_val = m_value;
m_value = fittedValue( _value );
if( old_val != m_value )
{
// add changes to history so user can undo it
addStep( editStep( 0, m_value - old_val ) );
// notify linked objects
// doesn't work because of implicit typename T
// for( autoObjVector::iterator it = m_linkedObjects.begin();
// it != m_linkedObjects.end(); ++it )
for( csize i = 0; i < m_linkedObjects.size(); ++i )
{
automatableObject<T> * it = m_linkedObjects[i];
if( value() != it->value() &&
it->fittedValue( value() ) != it->value() )
{
const bool sr = it->isRecordingSteps();
it->setStepRecording( isRecordingSteps() );
it->setValue( value() );
it->setStepRecording( sr );
}
}
}
}
@@ -117,7 +167,7 @@ public:
}
inline virtual void setRange( const T _min, const T _max,
const T _step = 0 )
const T _step = defaultRelStep() )
{
m_minValue = _min;
m_maxValue = _max;
@@ -127,7 +177,7 @@ public:
qSwap<T>( m_minValue, m_maxValue );
}
// re-adjust value
setValue( value() );
automatableObject<T>::setInitValue( value() );
}
inline virtual void setStep( const T _step )
@@ -159,6 +209,63 @@ public:
m_step = _step;
}
inline void linkObject( automatableObject<T> * _object )
{
if( qFind( m_linkedObjects.begin(), m_linkedObjects.end(),
_object ) == m_linkedObjects.end() )
{
m_linkedObjects.push_back( _object );
}
}
inline void unlinkObject( automatableObject<T> * _object )
{
m_linkedObjects.erase( qFind( m_linkedObjects.begin(),
m_linkedObjects.end(),
_object ) );
}
static inline void linkObjects( automatableObject<T> * _object1,
automatableObject<T> * _object2 )
{
_object1->linkObject( _object2 );
_object2->linkObject( _object1 );
}
protected:
virtual void redoStep( const editStep & _edit_step )
{
const bool sr = isRecordingSteps();
setStepRecording( FALSE );
#ifndef QT3
setValue( value() + _edit_step.data().value<T>() );
#else
setValue( value() + static_cast<T>(
_edit_step.data().toDouble() ) );
#endif
setStepRecording( sr );
}
virtual void undoStep( const editStep & _edit_step )
{
#ifndef QT3
redoStep( editStep( _edit_step.actionID(),
-_edit_step.data().value<T>() ) );
#else
redoStep( editStep( _edit_step.actionID(),
static_cast<T>( -_edit_step.data().toDouble() ) ) );
#endif
}
// most objects will need this temporarily
T m_oldValue;
inline void addStepFromOldToCurVal( void )
{
addStep( editStep( 0, value() - m_oldValue ) );
}
private:
T m_value;
@@ -166,6 +273,9 @@ private:
T m_maxValue;
T m_step;
typedef vvector<automatableObject<T> *> autoObjVector;
autoObjVector m_linkedObjects;
} ;

View File

@@ -46,14 +46,17 @@
#endif
#include "automatable_object.h"
class QAction;
class comboBox : public QWidget
class comboBox : public QWidget, public automatableObject<int>
{
Q_OBJECT
public:
comboBox( QWidget * _parent );
comboBox( QWidget * _parent, engine * _engine );
virtual ~comboBox();
void addItem( const QString & _item, const QPixmap & _pixmap =
@@ -61,26 +64,19 @@ public:
inline void clear( void )
{
m_currentIndex = 0;
setRange( 0, 0 );
m_items.clear();
update();
}
int findText( const QString & _txt ) const;
int currentIndex( void ) const
{
return( m_currentIndex );
}
QString currentText( void ) const
{
return( m_items[m_currentIndex].first );
return( m_items[value()].first );
}
public slots:
void setCurrentIndex( int _idx );
void setValue( const int _idx );
protected:
@@ -98,7 +94,6 @@ private:
typedef QPair<QString, QPixmap> item;
vvector<item> m_items;
int m_currentIndex;
bool m_pressed;
@@ -110,7 +105,7 @@ private slots:
signals:
void activated( const QString & );
void currentIndexChanged( int );
void valueChanged( int );
} ;

View File

@@ -26,10 +26,8 @@
#ifndef _ENGINE_H
#define _ENGINE_H
#include "qt3support.h"
class bbEditor;
class editHistory;
class mainWindow;
class mixer;
class pianoRoll;
@@ -40,7 +38,7 @@ class songEditor;
class engine
{
public:
engine( const bool _has_gui = TRUE );
engine( const bool _has_gui = true );
engine( const engine & _engine );
~engine();
@@ -94,6 +92,11 @@ public:
return( m_projectNotes );
}
inline editHistory * getEditHistory( void )
{
return( m_editHistory );
}
private:
bool m_hasGUI;
@@ -104,6 +107,7 @@ private:
bbEditor * m_bbEditor;
pianoRoll * m_pianoRoll;
projectNotes * m_projectNotes;
editHistory * m_editHistory;
} ;

View File

@@ -58,6 +58,7 @@
class QPaintEvent;
class QPixmap;
class automatableButtonGroup;
class envelopeTabWidget;
class knob;
class ledCheckBox;
@@ -119,10 +120,7 @@ protected:
protected slots:
void updateAfterKnobChange( float );
void lfoSinWaveCh( bool );
void lfoTriangleWaveCh( bool );
void lfoSawWaveCh( bool );
void lfoSquareWaveCh( bool );
void lfoWaveCh( int );
void lfoUserWaveCh( bool );
void x100Toggled( bool );
@@ -159,11 +157,8 @@ private:
knob * m_lfoAttackKnob;
tempoSyncKnob * m_lfoSpeedKnob;
knob * m_lfoAmountKnob;
pixmapButton * m_sinLfoBtn;
pixmapButton * m_triangleLfoBtn;
pixmapButton * m_sawLfoBtn;
pixmapButton * m_sqrLfoBtn;
pixmapButton * m_usrLfoBtn;
pixmapButton * m_userLfoBtn;
automatableButtonGroup * m_lfoWaveBtnGrp;
ledCheckBox * m_x100Cb;
ledCheckBox * m_controlEnvAmountCb;

View File

@@ -40,23 +40,21 @@
#include "pixmap_button.h"
class QPixmap;
class groupBox : public QWidget
class groupBox : public QWidget, public engineObject
{
Q_OBJECT
public:
groupBox( const QString & _caption, QWidget * _parent );
groupBox( const QString & _caption, QWidget * _parent,
engine * _engine );
virtual ~groupBox();
bool isActive( void ) const
{
#ifdef QT4
return( m_led->isChecked() );
#else
return( m_led->isOn() );
#endif
}

127
include/import_filter.h Executable file
View File

@@ -0,0 +1,127 @@
/*
* import_filter.h - declaration of class importFilter, the base-class for all
* file import filters
*
* Copyright (c) 2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#ifndef _IMPORT_FILTER_H
#define _IMPORT_FILTER_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "qt3support.h"
#ifdef QT4
#include <QFile>
#else
#include <qfile.h>
#endif
#include "plugin.h"
class trackContainer;
class importFilter : public plugin
{
public:
importFilter( const QString & _file_name,
const descriptor * _descriptor, engine * _eng );
virtual ~importFilter();
// tries to import given file to given track-container by having all
// available import-filters to try to import the file
static void FASTCALL import( const QString & _file_to_import,
trackContainer * _tc );
protected:
virtual bool tryImport( trackContainer * _tc ) = 0;
const QFile & file( void ) const
{
return( m_file );
}
bool openFile( void );
inline void closeFile( void )
{
m_file.close();
}
inline int readByte( void )
{
#ifdef QT4
char c;
if( m_file.getChar( &c ) )
{
return( static_cast<int>( c ) );
}
return( -1 );
#else
return( m_file.getch() );
#endif
}
inline void ungetChar( int _ch )
{
#ifndef QT3
m_file.ungetChar( _ch );
#else
m_file.ungetch( _ch );
#endif
}
virtual void FASTCALL saveSettings( QDomDocument &,
QDomElement & )
{
}
virtual void FASTCALL loadSettings( const QDomElement & )
{
}
virtual QString nodeName( void ) const
{
return( "import_filter" );
}
private:
QFile m_file;
} ;
#endif

View File

@@ -59,8 +59,7 @@ enum knobTypes
class knob : public QWidget, public engineObject,
public automatableObject<float>
class knob : public QWidget, public automatableObject<float>
{
Q_OBJECT
public:
@@ -75,10 +74,10 @@ public:
void setTotalAngle( float _angle );
inline void setInitValue( const float _val )
inline virtual void setInitValue( const float _val )
{
m_initValue = _val;
setValue( _val );
automatableObject<float>::setInitValue( _val );
}
virtual void setValue( const float _x );
@@ -86,33 +85,8 @@ public:
virtual void setRange( const float _min, const float _max,
const float _step = 0.0 );
/* inline float value( void ) const
{
return( m_value );
}
void setStep( float );
inline float maxValue( void ) const
{
return( m_maxValue );
}
inline float minValue( void ) const
{
return( m_minValue );
}*/
/* inline void incPages( int _n_pages )
{
setNewValue( value() + float( _n_pages ) * m_pageSize, 1 );
}*/
public slots:
/* void setValue( float _val, bool _is_init_value = FALSE );
void fitValue( float _val );
void incValue( int _steps );*/
void reset( void );
void copyValue( void );
void pasteValue( void );
@@ -173,6 +147,7 @@ protected:
float m_angle;
float m_totalAngle;
QPixmap * m_knobPixmap;
int m_knobNum;
QString m_hintTextBeforeValue;

View File

@@ -51,16 +51,12 @@ class lcdSpinBox : public QWidget, public automatableObject<int>
{
Q_OBJECT
public:
lcdSpinBox( int _min, int _max, int _num_digits, QWidget * _parent );
lcdSpinBox( int _min, int _max, int _num_digits, QWidget * _parent,
engine * _engine );
virtual ~lcdSpinBox();
virtual void setStep( const int _step );
/* inline int value( void ) const
{
return( m_number->intValue() );
}*/
void setLabel( const QString & _txt );
inline void addTextForValue( int _val, const QString & _text )
@@ -84,11 +80,6 @@ protected:
private:
QMap<int, QString> m_textForValue;
/* int m_value;
int m_minValue;
int m_maxValue;
int m_step;*/
QLCDNumber * m_number;
QLabel * m_label;

View File

@@ -26,26 +26,13 @@
#ifndef _LED_CHECKBOX_H
#define _LED_CHECKBOX_H
#include "qt3support.h"
#ifdef QT4
#include <QWidget>
#else
#include <qwidget.h>
#endif
#include "automatable_object.h"
#include "automatable_button.h"
class QPixmap;
class ledCheckBox : public QWidget, public automatableObject<bool>
class ledCheckBox : public automatableButton
{
Q_OBJECT
public:
@@ -54,30 +41,19 @@ public:
YELLOW, GREEN, TOTAL_COLORS
} ;
ledCheckBox( const QString & _txt, QWidget * _parent,
ledCheckBox( const QString & _txt, QWidget * _parent, engine * _engine,
ledColors _color = YELLOW );
virtual ~ledCheckBox();
inline bool isChecked( void ) const
{
return( value() );
}
inline const QString & text( void )
{
return( m_text );
}
public slots:
void toggle( void );
void setChecked( bool _on );
protected:
virtual void paintEvent( QPaintEvent * _pe );
virtual void mousePressEvent( QMouseEvent * _me );
private:
@@ -85,9 +61,6 @@ private:
QPixmap * m_ledOffPixmap;
QString m_text;
signals:
void toggled( bool );
} ;

View File

@@ -52,6 +52,7 @@
#include "engine.h"
class QDomElement;
class QGridLayout;
class QSplashScreen;
@@ -59,7 +60,6 @@ class configManager;
class toolButton;
class mainWindow : public QMainWindow, public engineObject
{
Q_OBJECT
@@ -98,6 +98,9 @@ public:
static QSplashScreen * s_splashScreen;
static void saveWidgetState( QWidget * _w, QDomElement & _de );
static void restoreWidgetState( QWidget * _w, const QDomElement & _de );
public slots:
inline void emptySlot( void )
@@ -120,6 +123,9 @@ public slots:
void toggleProjectNotesWin( void );
void togglePianoRollWin( void );
void undo( void );
void redo( void );
protected:
virtual void closeEvent( QCloseEvent * _ce );

View File

@@ -46,6 +46,7 @@
#include "types.h"
#include "note.h"
#include "engine.h"
#include "settings.h"
class QPainter;
@@ -59,7 +60,7 @@ class timeLine;
class toolButton;
class pianoRoll : public QWidget, public engineObject
class pianoRoll : public QWidget, public engineObject, public settings
{
Q_OBJECT
public:
@@ -83,6 +84,15 @@ public:
int quantization( void ) const;
virtual void FASTCALL saveSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void FASTCALL loadSettings( const QDomElement & _this );
inline virtual QString nodeName( void ) const
{
return( "pianoroll" );
}
public slots:
virtual void update( void );

View File

@@ -26,48 +26,32 @@
#ifndef _PIXMAP_BUTTON_H
#define _PIXMAP_BUTTON_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "qt3support.h"
#ifdef QT4
#include <QPushButton>
#include <QPixmap>
#else
#include <qpushbutton.h>
#include <qpixmap.h>
#endif
#include "automatable_button.h"
class pixmapButton : public QPushButton
class pixmapButton : public automatableButton
{
Q_OBJECT
public:
pixmapButton( QWidget * _parent );
pixmapButton( QWidget * _parent, engine * _engine );
virtual ~pixmapButton();
void FASTCALL setActiveGraphic( const QPixmap & _pm );
void FASTCALL setInactiveGraphic( const QPixmap & _pm,
bool _update = TRUE );
void FASTCALL setBgGraphic( const QPixmap & _pm );
#ifdef QT3
inline void setChecked( bool _on )
{
setOn( _on );
}
inline bool isChecked( void ) const
{
return( isOn() );
}
#endif
void setActiveGraphic( const QPixmap & _pm );
void setInactiveGraphic( const QPixmap & _pm, bool _update = TRUE );
void setBgGraphic( const QPixmap & _pm );
signals:
@@ -82,9 +66,9 @@ protected:
private:
QPixmap * m_activePixmap;
QPixmap * m_inactivePixmap;
QPixmap * m_bgPixmap;
QPixmap m_activePixmap;
QPixmap m_inactivePixmap;
QPixmap m_bgPixmap;
} ;

View File

@@ -135,10 +135,6 @@ inline QString baseName( const QString & _file )
#define modifiers state
// QButtonGroup
#define addButton insert
// QProgressBar
#define setTextVisible setPercentageVisible

View File

@@ -47,7 +47,7 @@ class nStateButton;
class textFloat;
class timeLine : public QWidget, public engineObject
class timeLine : public QWidget, public engineObject, public settings
{
Q_OBJECT
public:
@@ -116,6 +116,15 @@ public:
void addToolButtons( QWidget * _tool_bar );
virtual void FASTCALL saveSettings( QDomDocument & _doc,
QDomElement & _parent );
virtual void FASTCALL loadSettings( const QDomElement & _this );
inline virtual QString nodeName( void ) const
{
return( "timeline" );
}
public slots:
void updatePosition( const midiTime & );
void updatePosition( void )