diff --git a/include/AutomationEditor.h b/include/AutomationEditor.h index 83b0a022b..856b6177e 100644 --- a/include/AutomationEditor.h +++ b/include/AutomationEditor.h @@ -29,6 +29,8 @@ #include #include +#include "Editor.h" + #include "lmms_basics.h" #include "JournallingObject.h" #include "MidiTime.h" @@ -36,7 +38,6 @@ #include "ComboBoxModel.h" #include "Knob.h" - class QPainter; class QPixmap; class QScrollBar; @@ -47,6 +48,7 @@ class Timeline; class ToolButton; + class AutomationEditor : public QWidget, public JournallingObject { Q_OBJECT @@ -69,16 +71,13 @@ public: int quantization() const; - virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName() const + QString nodeName() const { - return( "automationeditor" ); + return "automationeditor"; } - void setPauseIcon( bool pause ); - // qproperty access methods QColor gridColor() const; QBrush graphColor() const; @@ -89,6 +88,14 @@ public: void setVertexColor( const QColor & c ); void setScaleColor( const QBrush & c ); + enum editModes + { + DRAW, + ERASE, + SELECT, + MOVE + }; + public slots: void update(); void updateAfterPatternChange(); @@ -97,7 +104,6 @@ public slots: protected: typedef AutomationPattern::timeMap timeMap; - virtual void closeEvent( QCloseEvent * _ce ); virtual void keyPressEvent( QKeyEvent * _ke ); virtual void leaveEvent( QEvent * _e ); virtual void mousePressEvent( QMouseEvent * _me ); @@ -117,7 +123,6 @@ protected: void getSelectedValues( timeMap & _selected_values ); void drawLine( int x0, float y0, int x1, float y1 ); - void disableTensionKnob(); protected slots: void play(); @@ -126,15 +131,14 @@ protected slots: void horScrolled( int _new_pos ); void verScrolled( int _new_pos ); - void drawButtonToggled(); - void eraseButtonToggled(); - void selectButtonToggled(); - void moveButtonToggled(); + void setEditMode(AutomationEditor::editModes mode); + void setEditMode(int mode); - void discreteButtonToggled(); - void linearButtonToggled(); - void cubicHermiteButtonToggled(); - void tensionChanged(); + void setProgressionType(AutomationPattern::ProgressionTypes type); + void setProgressionDiscrete(); + void setProgressionLinear(); + void setProgressionHermite(); + void setTension(); void copySelectedValues(); void cutSelectedValues(); @@ -149,14 +153,6 @@ protected slots: private: - enum editModes - { - DRAW, - ERASE, - SELECT, - MOVE - } ; - enum actions { NONE, @@ -166,11 +162,8 @@ private: } ; // some constants... - static const int INITIAL_WIDTH = 860; - static const int INITIAL_HEIGHT = 480; - static const int SCROLLBAR_SIZE = 16; - static const int TOP_MARGIN = 48; + static const int TOP_MARGIN = 16; static const int DEFAULT_Y_DELTA = 6; static const int DEFAULT_STEPS_PER_TACT = 16; @@ -182,41 +175,17 @@ private: AutomationEditor( const AutomationEditor & ); virtual ~AutomationEditor(); - static QPixmap * s_toolDraw; static QPixmap * s_toolErase; static QPixmap * s_toolSelect; static QPixmap * s_toolMove; - - QWidget * m_toolBar; - - ToolButton * m_playButton; - ToolButton * m_stopButton; - - ToolButton * m_drawButton; - ToolButton * m_eraseButton; - ToolButton * m_selectButton; - ToolButton * m_moveButton; - - ToolButton * m_discreteButton; - ToolButton * m_linearButton; - ToolButton * m_cubicHermiteButton; - Knob * m_tensionKnob; - FloatModel * m_tensionModel; - - ToolButton * m_cutButton; - ToolButton * m_copyButton; - ToolButton * m_pasteButton; - - ComboBox * m_zoomingXComboBox; - ComboBox * m_zoomingYComboBox; - ComboBox * m_quantizeComboBox; - ComboBoxModel m_zoomingXModel; ComboBoxModel m_zoomingYModel; ComboBoxModel m_quantizeModel; + FloatModel * m_tensionModel; + QMutex m_patternMutex; AutomationPattern * m_pattern; float m_minLevel; @@ -270,14 +239,64 @@ private: QColor m_vertexColor; QBrush m_scaleColor; - friend class Engine; + //friend class Engine; + friend class AutomationEditorWindow; signals: void currentPatternChanged(); void positionChanged( const MidiTime & ); - } ; + +class AutomationEditorWindow : public Editor +{ + Q_OBJECT + + static const int INITIAL_WIDTH = 860; + static const int INITIAL_HEIGHT = 480; +public: + AutomationEditorWindow(); + ~AutomationEditorWindow(); + + void setCurrentPattern(AutomationPattern* pattern); + const AutomationPattern* currentPattern(); + + int quantization() const; + + AutomationEditor* m_editor; + + virtual void closeEvent( QCloseEvent * _ce ); + +signals: + void currentPatternChanged(); + +protected slots: + void play(); + void stop(); + +private: + QAbstractButton * m_drawButton; + QAbstractButton * m_eraseButton; + QAbstractButton * m_selectButton; + QAbstractButton * m_moveButton; + + ToolButton * m_discreteButton; + ToolButton * m_linearButton; + ToolButton * m_cubicHermiteButton; + Knob * m_tensionKnob; + + ToolButton * m_cutButton; + ToolButton * m_copyButton; + ToolButton * m_pasteButton; + + ComboBox * m_zoomingXComboBox; + ComboBox * m_zoomingYComboBox; + ComboBox * m_quantizeComboBox; + + friend class Engine; +}; + + #endif diff --git a/include/Editor.h b/include/Editor.h index 0416f0369..ccc4af494 100644 --- a/include/Editor.h +++ b/include/Editor.h @@ -39,7 +39,7 @@ class Editor : public QMainWindow { Q_OBJECT public: - void setPlaying(bool playing=true); + void setPauseIcon(bool displayPauseIcon=true); signals: diff --git a/include/Engine.h b/include/Engine.h index b7839f817..827d72e65 100644 --- a/include/Engine.h +++ b/include/Engine.h @@ -33,7 +33,7 @@ #include "export.h" -class AutomationEditor; +class AutomationEditorWindow; class BBEditor; class BBTrackContainer; class DummyTrackContainer; @@ -128,7 +128,7 @@ public: return s_projectNotes; } - static AutomationEditor * automationEditor() + static AutomationEditorWindow * automationEditor() { return s_automationEditor; } @@ -188,7 +188,7 @@ private: static MainWindow * s_mainWindow; static FxMixerView * s_fxMixerView; static SongEditor* s_songEditor; - static AutomationEditor * s_automationEditor; + static AutomationEditorWindow * s_automationEditor; static BBEditor * s_bbEditor; static PianoRoll* s_pianoRoll; static ProjectNotes * s_projectNotes; diff --git a/src/core/Engine.cpp b/src/core/Engine.cpp index 67a6a669f..a921fde56 100644 --- a/src/core/Engine.cpp +++ b/src/core/Engine.cpp @@ -56,7 +56,7 @@ MainWindow * Engine::s_mainWindow = NULL; BBTrackContainer * Engine::s_bbTrackContainer = NULL; Song * Engine::s_song = NULL; SongEditor* Engine::s_songEditor = NULL; -AutomationEditor * Engine::s_automationEditor = NULL; +AutomationEditorWindow * Engine::s_automationEditor = NULL; BBEditor * Engine::s_bbEditor = NULL; PianoRoll* Engine::s_pianoRoll = NULL; ProjectNotes * Engine::s_projectNotes = NULL; @@ -99,7 +99,7 @@ void Engine::init( const bool _has_gui ) s_projectNotes = new ProjectNotes; s_bbEditor = new BBEditor( s_bbTrackContainer ); s_pianoRoll = new PianoRoll; - s_automationEditor = new AutomationEditor; + s_automationEditor = new AutomationEditorWindow; s_mainWindow->finalize(); } diff --git a/src/core/Song.cpp b/src/core/Song.cpp index ce686e79f..cd1a642e1 100644 --- a/src/core/Song.cpp +++ b/src/core/Song.cpp @@ -958,9 +958,9 @@ void Song::loadProject( const QString & _file_name ) { Engine::pianoRoll()->restoreState( node.toElement() ); } - else if( node.nodeName() == Engine::automationEditor()->nodeName() ) + else if( node.nodeName() == Engine::automationEditor()->m_editor->nodeName() ) { - Engine::automationEditor()->restoreState( node.toElement() ); + Engine::automationEditor()->m_editor->restoreState( node.toElement() ); } else if( node.nodeName() == Engine::getProjectNotes()->nodeName() ) { @@ -1027,7 +1027,7 @@ bool Song::saveProjectFile( const QString & _filename ) { Engine::getControllerRackView()->saveState( dataFile, dataFile.content() ); Engine::pianoRoll()->saveState( dataFile, dataFile.content() ); - Engine::automationEditor()->saveState( dataFile, dataFile.content() ); + Engine::automationEditor()->m_editor->saveState( dataFile, dataFile.content() ); Engine::getProjectNotes()->SerializingObject::saveState( dataFile, dataFile.content() ); m_playPos[Mode_PlaySong].m_timeLine->saveState( dataFile, dataFile.content() ); } diff --git a/src/gui/AutomationEditor.cpp b/src/gui/AutomationEditor.cpp index f47d8165b..a80b118d8 100644 --- a/src/gui/AutomationEditor.cpp +++ b/src/gui/AutomationEditor.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #ifndef __USE_XOPEN @@ -107,6 +108,43 @@ AutomationEditor::AutomationEditor() : Qt::QueuedConnection ); connect( Engine::getSong(), SIGNAL( timeSignatureChanged( int, int ) ), this, SLOT( update() ) ); + + setAttribute( Qt::WA_OpaquePaintEvent, true ); + + m_tensionModel = new FloatModel(1.0, 0.0, 1.0, 0.01); + connect( m_tensionModel, SIGNAL( dataChanged() ), + this, SLOT( setTension() ) ); + + for( int i = 0; i < 7; ++i ) + { + m_quantizeModel.addItem( "1/" + QString::number( 1 << i ) ); + } + m_quantizeModel.setValue( m_quantizeModel.findText( "1/16" ) ); + + // add time-line + m_timeLine = new Timeline( VALUES_WIDTH, 0, m_ppt, + Engine::getSong()->getPlayPos( + Song::Mode_PlayAutomationPattern ), + m_currentPosition, this ); + connect( this, SIGNAL( positionChanged( const MidiTime & ) ), + m_timeLine, SLOT( updatePosition( const MidiTime & ) ) ); + connect( m_timeLine, SIGNAL( positionChanged( const MidiTime & ) ), + this, SLOT( updatePosition( const MidiTime & ) ) ); + + removeSelection(); + + // init scrollbars + m_leftRightScroll = new QScrollBar( Qt::Horizontal, this ); + m_leftRightScroll->setSingleStep( 1 ); + connect( m_leftRightScroll, SIGNAL( valueChanged( int ) ), this, + SLOT( horScrolled( int ) ) ); + + m_topBottomScroll = new QScrollBar( Qt::Vertical, this ); + m_topBottomScroll->setSingleStep( 1 ); + m_topBottomScroll->setPageStep( 20 ); + connect( m_topBottomScroll, SIGNAL( valueChanged( int ) ), this, + SLOT( verScrolled( int ) ) ); + // init pixmaps if( s_toolDraw == NULL ) { @@ -129,324 +167,9 @@ AutomationEditor::AutomationEditor() : "edit_move" ) ); } - setAttribute( Qt::WA_OpaquePaintEvent, true ); - - // add time-line - m_timeLine = new Timeline( VALUES_WIDTH, 32, m_ppt, - Engine::getSong()->getPlayPos( - Song::Mode_PlayAutomationPattern ), - m_currentPosition, this ); - connect( this, SIGNAL( positionChanged( const MidiTime & ) ), - m_timeLine, SLOT( updatePosition( const MidiTime & ) ) ); - connect( m_timeLine, SIGNAL( positionChanged( const MidiTime & ) ), - this, SLOT( updatePosition( const MidiTime & ) ) ); - - - m_toolBar = new QWidget( this ); - m_toolBar->setFixedHeight( 32 ); - m_toolBar->move( 0, 0 ); - m_toolBar->setAutoFillBackground( true ); - QPalette pal; - pal.setBrush( m_toolBar->backgroundRole(), - embed::getIconPixmap( "toolbar_bg" ) ); - m_toolBar->setPalette( pal ); - - QHBoxLayout * tb_layout = new QHBoxLayout( m_toolBar ); - tb_layout->setMargin( 0 ); - tb_layout->setSpacing( 0 ); - - - // init control-buttons at the top - - m_playButton = new ToolButton( embed::getIconPixmap( "play" ), - tr( "Play/pause current pattern (Space)" ), - this, SLOT( play() ), m_toolBar ); - - - m_stopButton = new ToolButton( embed::getIconPixmap( "stop" ), - tr( "Stop playing of current pattern (Space)" ), - this, SLOT( stop() ), m_toolBar ); - - m_playButton->setObjectName( "playButton" ); - m_stopButton->setObjectName( "stopButton" ); - - m_playButton->setWhatsThis( - tr( "Click here if you want to play the current pattern. " - "This is useful while editing it. The pattern is " - "automatically looped when the end is reached." ) ); - m_stopButton->setWhatsThis( - tr( "Click here if you want to stop playing of the " - "current pattern." ) ); - - removeSelection(); - - // init scrollbars - m_leftRightScroll = new QScrollBar( Qt::Horizontal, this ); - m_leftRightScroll->setSingleStep( 1 ); - connect( m_leftRightScroll, SIGNAL( valueChanged( int ) ), this, - SLOT( horScrolled( int ) ) ); - - m_topBottomScroll = new QScrollBar( Qt::Vertical, this ); - m_topBottomScroll->setSingleStep( 1 ); - m_topBottomScroll->setPageStep( 20 ); - connect( m_topBottomScroll, SIGNAL( valueChanged( int ) ), this, - SLOT( verScrolled( int ) ) ); - - // init edit-buttons at the top - m_drawButton = new ToolButton( embed::getIconPixmap( "edit_draw" ), - tr( "Draw mode (Shift+D)" ), - this, SLOT( drawButtonToggled() ), - m_toolBar ); - m_drawButton->setCheckable( true ); - m_drawButton->setChecked( true ); - - m_eraseButton = new ToolButton( embed::getIconPixmap( "edit_erase" ), - tr( "Erase mode (Shift+E)" ), - this, SLOT( eraseButtonToggled() ), - m_toolBar ); - m_eraseButton->setCheckable( true ); - - //TODO: m_selectButton and m_moveButton are broken. - /*m_selectButton = new toolButton( embed::getIconPixmap( - "edit_select" ), - tr( "Select mode (Shift+S)" ), - this, SLOT( selectButtonToggled() ), - m_toolBar ); - m_selectButton->setCheckable( true ); - - m_moveButton = new toolButton( embed::getIconPixmap( "edit_move" ), - tr( "Move selection mode (Shift+M)" ), - this, SLOT( moveButtonToggled() ), - m_toolBar ); - m_moveButton->setCheckable( true );*/ - - QButtonGroup * tool_button_group = new QButtonGroup( this ); - tool_button_group->addButton( m_drawButton ); - tool_button_group->addButton( m_eraseButton ); - //tool_button_group->addButton( m_selectButton ); - //tool_button_group->addButton( m_moveButton ); - tool_button_group->setExclusive( true ); - - m_drawButton->setWhatsThis( - tr( "Click here and draw-mode will be activated. In this " - "mode you can add and move single values. This " - "is the default mode which is used most of the time. " - "You can also press 'Shift+D' on your keyboard to " - "activate this mode." ) ); - m_eraseButton->setWhatsThis( - tr( "Click here and erase-mode will be activated. In this " - "mode you can erase single values. You can also press " - "'Shift+E' on your keyboard to activate this mode." ) ); - /*m_selectButton->setWhatsThis( - tr( "Click here and select-mode will be activated. In this " - "mode you can select values. This is necessary " - "if you want to cut, copy, paste, delete, or move " - "values. You can also press 'Shift+S' on your keyboard " - "to activate this mode." ) ); - m_moveButton->setWhatsThis( - tr( "If you click here, move-mode will be activated. In this " - "mode you can move the values you selected in select-" - "mode. You can also press 'Shift+M' on your keyboard " - "to activate this mode." ) );*/ - - m_discreteButton = new ToolButton( embed::getIconPixmap( - "progression_discrete" ), - tr( "Discrete progression" ), - this, SLOT( discreteButtonToggled() ), - m_toolBar ); - m_discreteButton->setCheckable( true ); - m_discreteButton->setChecked( true ); - - m_linearButton = new ToolButton( embed::getIconPixmap( - "progression_linear" ), - tr( "Linear progression" ), - this, SLOT( linearButtonToggled() ), - m_toolBar ); - m_linearButton->setCheckable( true ); - - m_cubicHermiteButton = new ToolButton( embed::getIconPixmap( - "progression_cubic_hermite" ), - tr( "Cubic Hermite progression" ), - this, SLOT( - cubicHermiteButtonToggled() ), - m_toolBar ); - m_cubicHermiteButton->setCheckable( true ); - - // setup tension-stuff - m_tensionKnob = new Knob( knobSmall_17, this, "Tension" ); - m_tensionModel = new FloatModel(1.0, 0.0, 1.0, 0.01); - connect( m_tensionModel, SIGNAL( dataChanged() ), - this, SLOT( tensionChanged() ) ); - - QLabel * tension_lbl = new QLabel( m_toolBar ); - tension_lbl->setText( tr("Tension: ") ); - - tool_button_group = new QButtonGroup( this ); - tool_button_group->addButton( m_discreteButton ); - tool_button_group->addButton( m_linearButton ); - tool_button_group->addButton( m_cubicHermiteButton ); - tool_button_group->setExclusive( true ); - - m_discreteButton->setWhatsThis( - tr( "Click here to choose discrete progressions for this " - "automation pattern. The value of the connected " - "object will remain constant between control points " - "and be set immediately to the new value when each " - "control point is reached." ) ); - m_linearButton->setWhatsThis( - tr( "Click here to choose linear progressions for this " - "automation pattern. The value of the connected " - "object will change at a steady rate over time " - "between control points to reach the correct value at " - "each control point without a sudden change." ) ); - m_cubicHermiteButton->setWhatsThis( - tr( "Click here to choose cubic hermite progressions for this " - "automation pattern. The value of the connected " - "object will change in a smooth curve and ease in to " - "the peaks and valleys." ) ); - - m_cutButton = new ToolButton( embed::getIconPixmap( "edit_cut" ), - tr( "Cut selected values (Ctrl+X)" ), - this, SLOT( cutSelectedValues() ), - m_toolBar ); - - m_copyButton = new ToolButton( embed::getIconPixmap( "edit_copy" ), - tr( "Copy selected values (Ctrl+C)" ), - this, SLOT( copySelectedValues() ), - m_toolBar ); - - m_pasteButton = new ToolButton( embed::getIconPixmap( "edit_paste" ), - tr( "Paste values from clipboard " - "(Ctrl+V)" ), - this, SLOT( pasteValues() ), - m_toolBar ); - - m_cutButton->setWhatsThis( - tr( "Click here and selected values will be cut into the " - "clipboard. You can paste them anywhere in any pattern " - "by clicking on the paste button." ) ); - m_copyButton->setWhatsThis( - tr( "Click here and selected values will be copied into " - "the clipboard. You can paste them anywhere in any " - "pattern by clicking on the paste button." ) ); - m_pasteButton->setWhatsThis( - tr( "Click here and the values from the clipboard will be " - "pasted at the first visible measure." ) ); - - - // setup zooming-stuff - QLabel * zoom_x_lbl = new QLabel( m_toolBar ); - zoom_x_lbl->setPixmap( embed::getIconPixmap( "zoom_x" ) ); - - m_zoomingXComboBox = new ComboBox( m_toolBar ); - m_zoomingXComboBox->setFixedSize( 80, 22 ); - - for( int i = 0; i < 6; ++i ) - { - m_zoomingXModel.addItem( QString::number( 25 << i ) + "%" ); - } - m_zoomingXModel.setValue( m_zoomingXModel.findText( "100%" ) ); - - m_zoomingXComboBox->setModel( &m_zoomingXModel ); - - connect( &m_zoomingXModel, SIGNAL( dataChanged() ), - this, SLOT( zoomingXChanged() ) ); - - - QLabel * zoom_y_lbl = new QLabel( m_toolBar ); - zoom_y_lbl->setPixmap( embed::getIconPixmap( "zoom_y" ) ); - - m_zoomingYComboBox = new ComboBox( m_toolBar ); - m_zoomingYComboBox->setFixedSize( 80, 22 ); - - m_zoomingYModel.addItem( "Auto" ); - for( int i = 0; i < 7; ++i ) - { - m_zoomingYModel.addItem( QString::number( 25 << i ) + "%" ); - } - m_zoomingYModel.setValue( m_zoomingYModel.findText( "Auto" ) ); - - m_zoomingYComboBox->setModel( &m_zoomingYModel ); - - connect( &m_zoomingYModel, SIGNAL( dataChanged() ), - this, SLOT( zoomingYChanged() ) ); - - - // setup quantize-stuff - QLabel * quantize_lbl = new QLabel( m_toolBar ); - quantize_lbl->setPixmap( embed::getIconPixmap( "quantize" ) ); - - m_quantizeComboBox = new ComboBox( m_toolBar ); - m_quantizeComboBox->setFixedSize( 60, 22 ); - - for( int i = 0; i < 7; ++i ) - { - m_quantizeModel.addItem( "1/" + QString::number( 1 << i ) ); - } - m_quantizeModel.setValue( m_quantizeModel.findText( "1/16" ) ); - - m_quantizeComboBox->setModel( &m_quantizeModel ); - - - tb_layout->addSpacing( 5 ); - tb_layout->addWidget( m_playButton ); - tb_layout->addWidget( m_stopButton ); - tb_layout->addSpacing( 10 ); - tb_layout->addWidget( m_drawButton ); - tb_layout->addWidget( m_eraseButton ); - //tb_layout->addWidget( m_selectButton ); - //tb_layout->addWidget( m_moveButton ); - tb_layout->addSpacing( 10 ); - tb_layout->addWidget( m_discreteButton ); - tb_layout->addWidget( m_linearButton ); - tb_layout->addWidget( m_cubicHermiteButton ); - tb_layout->addSpacing( 5 ); - tb_layout->addWidget( tension_lbl ); - tb_layout->addSpacing( 5 ); - tb_layout->addWidget( m_tensionKnob ); - tb_layout->addSpacing( 10 ); - tb_layout->addWidget( m_cutButton ); - tb_layout->addWidget( m_copyButton ); - tb_layout->addWidget( m_pasteButton ); - tb_layout->addSpacing( 10 ); - m_timeLine->addToolButtons( m_toolBar ); - tb_layout->addSpacing( 15 ); - tb_layout->addWidget( zoom_x_lbl ); - tb_layout->addSpacing( 4 ); - tb_layout->addWidget( m_zoomingXComboBox ); - tb_layout->addSpacing( 10 ); - tb_layout->addWidget( zoom_y_lbl ); - tb_layout->addSpacing( 4 ); - tb_layout->addWidget( m_zoomingYComboBox ); - tb_layout->addSpacing( 10 ); - tb_layout->addWidget( quantize_lbl ); - tb_layout->addSpacing( 4 ); - tb_layout->addWidget( m_quantizeComboBox ); - tb_layout->addStretch(); - - // setup our actual window - setFocusPolicy( Qt::StrongFocus ); - setFocus(); - setWindowIcon( embed::getIconPixmap( "automation" ) ); setCurrentPattern( NULL ); setMouseTracking( true ); - - setMinimumSize( tb_layout->minimumSize().width(), 128 ); - - // add us to workspace - if( Engine::mainWindow()->workspace() ) - { - Engine::mainWindow()->workspace()->addSubWindow( this ); - parentWidget()->resize( INITIAL_WIDTH, INITIAL_HEIGHT ); - parentWidget()->move( 5, 5 ); - parentWidget()->hide(); - } - else - { - resize( INITIAL_WIDTH, INITIAL_HEIGHT ); - hide(); - } } @@ -492,19 +215,6 @@ void AutomationEditor::loadSettings( const QDomElement & _this ) - -void AutomationEditor::setPauseIcon( bool pause ) -{ - if( pause == true ) - { - m_playButton->setIcon( embed::getIconPixmap( "pause" ) ); - } - else - { - m_playButton->setIcon( embed::getIconPixmap( "play" ) ); - } -} - // qproperty access methods QColor AutomationEditor::gridColor() const @@ -541,27 +251,6 @@ void AutomationEditor::updateAfterPatternChange() return; } - if( m_pattern->progressionType() == - AutomationPattern::DiscreteProgression && - !m_discreteButton->isChecked() ) - { - m_discreteButton->setChecked( true ); - } - - if( m_pattern->progressionType() == - AutomationPattern::LinearProgression && - !m_linearButton->isChecked() ) - { - m_linearButton->setChecked( true ); - } - - if( m_pattern->progressionType() == - AutomationPattern::CubicHermiteProgression && - !m_cubicHermiteButton->isChecked() ) - { - m_cubicHermiteButton->setChecked( true ); - } - m_minLevel = m_pattern->firstObject()->minValue(); m_maxLevel = m_pattern->firstObject()->maxValue(); m_step = m_pattern->firstObject()->step(); @@ -605,23 +294,6 @@ void AutomationEditor::removeSelection() -void AutomationEditor::closeEvent( QCloseEvent * _ce ) -{ - QApplication::restoreOverrideCursor(); - if( parentWidget() ) - { - parentWidget()->hide(); - } - else - { - hide(); - } - _ce->ignore(); -} - - - - void AutomationEditor::keyPressEvent( QKeyEvent * _ke ) { switch( _ke->key() ) @@ -685,44 +357,12 @@ void AutomationEditor::keyPressEvent( QKeyEvent * _ke ) update(); _ke->accept(); } - break;*/ - - case Qt::Key_D: - if( _ke->modifiers() & Qt::ShiftModifier ) - { - m_drawButton->setChecked( true ); - _ke->accept(); - } break; - case Qt::Key_E: - if( _ke->modifiers() & Qt::ShiftModifier ) - { - m_eraseButton->setChecked( true ); - _ke->accept(); - } - break; - //TODO: m_selectButton and m_moveButton are broken. - /*case Qt::Key_S: - if( _ke->modifiers() & Qt::ShiftModifier ) - { - m_selectButton->setChecked( true ); - _ke->accept(); - } - break; - - case Qt::Key_M: - if( _ke->modifiers() & Qt::ShiftModifier ) - { - m_moveButton->setChecked( true ); - _ke->accept(); - } - break;*/ - case Qt::Key_Delete: deleteSelectedValues(); _ke->accept(); - break; + break;*/ case Qt::Key_Space: if( Engine::getSong()->isPlaying() ) @@ -812,14 +452,6 @@ void AutomationEditor::drawLine( int _x0, float _y0, int _x1, float _y1 ) -void AutomationEditor::disableTensionKnob() -{ - m_tensionKnob->setEnabled( false ); -} - - - - void AutomationEditor::mousePressEvent( QMouseEvent * _me ) { QMutexLocker m( &m_patternMutex ); @@ -941,7 +573,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent * _me ) { // when clicking right in select-move, we // switch to move-mode - m_moveButton->setChecked( true ); + //m_moveButton->setChecked( true ); } else if( _me->button() == Qt::LeftButton && m_editMode == MOVE ) @@ -961,7 +593,7 @@ void AutomationEditor::mousePressEvent( QMouseEvent * _me ) { // when clicking right in select-move, we // switch to draw-mode - m_drawButton->setChecked( true ); + //m_drawButton->setChecked( true ); } update(); @@ -1822,7 +1454,6 @@ void AutomationEditor::resizeEvent( QResizeEvent * ) Engine::getSong()->getPlayPos( Song::Mode_PlayAutomationPattern ).m_timeLine->setFixedWidth( width() ); } - m_toolBar->setFixedWidth( width() ); updateTopBottomLevels(); update(); @@ -1960,8 +1591,6 @@ void AutomationEditor::play() Engine::getSong()->togglePause(); } } - - setPauseIcon( Engine::getSong()->isPlaying() ); } @@ -2009,102 +1638,69 @@ void AutomationEditor::verScrolled( int _new_pos ) -void AutomationEditor::drawButtonToggled() +void AutomationEditor::setEditMode(AutomationEditor::editModes mode) { - m_editMode = DRAW; - removeSelection(); - update(); -} + if (m_editMode == mode) + return; - - - -void AutomationEditor::eraseButtonToggled() -{ - m_editMode = ERASE; - removeSelection(); - update(); -} - - - - -void AutomationEditor::selectButtonToggled() -{ - m_editMode = SELECT; - removeSelection(); - update(); -} - - - - -void AutomationEditor::moveButtonToggled() -{ - m_editMode = MOVE; - m_selValuesForMove.clear(); - getSelectedValues( m_selValuesForMove ); - update(); -} - - - - -void AutomationEditor::discreteButtonToggled() -{ - if ( validPattern() ) + m_editMode = mode; + switch (mode) { - QMutexLocker m( &m_patternMutex ); - disableTensionKnob(); - m_pattern->setProgressionType( - AutomationPattern::DiscreteProgression ); + case DRAW: + case ERASE: + case SELECT: + removeSelection(); + break; + case MOVE: + m_selValuesForMove.clear(); + getSelectedValues(m_selValuesForMove); + } + update(); +} + + + +void AutomationEditor::setEditMode(int mode) +{ + setEditMode((AutomationEditor::editModes) mode); +} + + + + +void AutomationEditor::setProgressionType(AutomationPattern::ProgressionTypes type) +{ + if (validPattern()) + { + QMutexLocker m(&m_patternMutex); + m_pattern->setProgressionType(type); Engine::getSong()->setModified(); update(); } } - - -void AutomationEditor::linearButtonToggled() +void AutomationEditor::setProgressionDiscrete() { - if ( validPattern() ) - { - QMutexLocker m( &m_patternMutex ); - disableTensionKnob(); - m_pattern->setProgressionType( - AutomationPattern::LinearProgression ); - Engine::getSong()->setModified(); - update(); - } + setProgressionType(AutomationPattern::DiscreteProgression); +} + + +void AutomationEditor::setProgressionLinear() +{ + setProgressionType(AutomationPattern::LinearProgression); +} + + +void AutomationEditor::setProgressionHermite() +{ + setProgressionType(AutomationPattern::CubicHermiteProgression); } -void AutomationEditor::cubicHermiteButtonToggled() -{ - if ( validPattern() ) - { - m_tensionKnob->setModel( m_tensionModel ); - m_tensionKnob->setEnabled( true ); - ToolTip::add( m_tensionKnob, tr( "Tension value for spline" ) ); - m_tensionKnob->setWhatsThis( - tr( "A higher tension value may make a smoother curve " - "but overshoot some values. A low tension " - "value will cause the slope of the curve to " - "level off at each control point." ) ); - m_pattern->setProgressionType( - AutomationPattern::CubicHermiteProgression ); - Engine::getSong()->setModified(); - update(); - } -} - - - - -void AutomationEditor::tensionChanged() +void AutomationEditor::setTension() { m_pattern->setTension( QString::number( m_tensionModel->value() ) ); update(); @@ -2366,10 +1962,7 @@ void AutomationEditor::zoomingYChanged() int AutomationEditor::quantization() const { - return( DefaultTicksPerTact / - m_quantizeComboBox->model()->currentText().right( - m_quantizeComboBox->model()->currentText().length() - - 2 ).toInt() ); + return DefaultTicksPerTact / (1 << m_quantizeModel.value()); } @@ -2425,3 +2018,357 @@ void AutomationEditor::updateTopBottomLevels() + + +AutomationEditorWindow::AutomationEditorWindow() : + Editor(), + m_editor(new AutomationEditor()) +{ + setCentralWidget(m_editor); + + + + // Play/stop buttons + m_playButton->setToolTip(tr( "Play/pause current pattern (Space)" )); + m_playButton->setWhatsThis( + tr( "Click here if you want to play the current pattern. " + "This is useful while editing it. The pattern is " + "automatically looped when the end is reached." ) ); + + m_stopButton->setToolTip(tr("Stop playing of current pattern (Space)")); + m_stopButton->setWhatsThis( + tr( "Click here if you want to stop playing of the " + "current pattern." ) ); + + // Set up signals) + connect(m_playButton, SIGNAL(clicked()), this, SLOT(play())); + connect(m_stopButton, SIGNAL(clicked()), this, SLOT(stop())); + + + // Edit mode buttons + + m_drawButton = new ToolButton(embed::getIconPixmap( "edit_draw" ), + tr( "Draw mode (Shift+D)" )); + m_drawButton->setCheckable( true ); + m_drawButton->setChecked( true ); + m_drawButton->setShortcut(Qt::SHIFT | Qt::Key_D); + + m_eraseButton = new ToolButton( embed::getIconPixmap( "edit_erase" ), + tr( "Erase mode (Shift+E)" )); + m_eraseButton->setCheckable( true ); + m_eraseButton->setShortcut(Qt::SHIFT | Qt::Key_E); + + //TODO: m_selectButton and m_moveButton are broken. + /*m_selectButton = new ToolButton( embed::getIconPixmap( + "edit_select" ), + tr( "Select mode (Shift+S)" ), + this, SLOT( selectButtonToggled() ), + m_toolBar ); + m_selectButton->setCheckable( true ); + + m_moveButton = new ToolButton( embed::getIconPixmap( "edit_move" ), + tr( "Move selection mode (Shift+M)" ), + this, SLOT( moveButtonToggled() ), + m_toolBar ); + m_moveButton->setCheckable( true );*/ + + QSignalMapper* signalmapper = new QSignalMapper(this); + signalmapper->setMapping(m_drawButton, AutomationEditor::DRAW); + signalmapper->setMapping(m_eraseButton, AutomationEditor::ERASE); +// signalmapper->setMapping(m_selectButton, AutomationEditor::SELECT); +// signalmapper->setMapping(m_moveButton, AutomationEditor::MOVE); + + connect(m_drawButton, SIGNAL(clicked()), signalmapper, SLOT(map())); + connect(m_eraseButton, SIGNAL(clicked()), signalmapper, SLOT(map())); +// connect(m_selectButton, SIGNAL(triggered()), signalmapper, SLOT(map())); +// connect(m_moveButton, SIGNAL(triggered()), signalmapper, SLOT(map())); + + connect(signalmapper, SIGNAL(mapped(int)), m_editor, SLOT(setEditMode(int))); + + QButtonGroup * tool_button_group = new QButtonGroup(); + tool_button_group->addButton( m_drawButton ); + tool_button_group->addButton( m_eraseButton ); + //tool_button_group->addButton( m_selectButton ); + //tool_button_group->addButton( m_moveButton ); + tool_button_group->setExclusive( true ); + + m_drawButton->setWhatsThis( + tr( "Click here and draw-mode will be activated. In this " + "mode you can add and move single values. This " + "is the default mode which is used most of the time. " + "You can also press 'Shift+D' on your keyboard to " + "activate this mode." ) ); + m_eraseButton->setWhatsThis( + tr( "Click here and erase-mode will be activated. In this " + "mode you can erase single values. You can also press " + "'Shift+E' on your keyboard to activate this mode." ) ); + /*m_selectButton->setWhatsThis( + tr( "Click here and select-mode will be activated. In this " + "mode you can select values. This is necessary " + "if you want to cut, copy, paste, delete, or move " + "values. You can also press 'Shift+S' on your keyboard " + "to activate this mode." ) ); + m_moveButton->setWhatsThis( + tr( "If you click here, move-mode will be activated. In this " + "mode you can move the values you selected in select-" + "mode. You can also press 'Shift+M' on your keyboard " + "to activate this mode." ) );*/ + + + + // Progression type buttons + + m_discreteButton = new ToolButton( embed::getIconPixmap( + "progression_discrete" ), + tr( "Discrete progression" ), + m_editor, SLOT( setProgressionDiscrete() ), + m_toolBar ); + m_discreteButton->setCheckable( true ); + m_discreteButton->setChecked( true ); + + m_linearButton = new ToolButton( embed::getIconPixmap( + "progression_linear" ), + tr( "Linear progression" ), + m_editor, SLOT( setProgressionLinear() ), + m_toolBar ); + m_linearButton->setCheckable( true ); + + m_cubicHermiteButton = new ToolButton( embed::getIconPixmap( + "progression_cubic_hermite" ), + tr( "Cubic Hermite progression" ), + m_editor, SLOT( + setProgressionHermite() ), + m_toolBar ); + m_cubicHermiteButton->setCheckable( true ); + + // setup tension-stuff + m_tensionKnob = new Knob( knobSmall_17, this, "Tension" ); + + tool_button_group = new QButtonGroup( this ); + tool_button_group->addButton( m_discreteButton ); + tool_button_group->addButton( m_linearButton ); + tool_button_group->addButton( m_cubicHermiteButton ); + tool_button_group->setExclusive( true ); + + m_discreteButton->setWhatsThis( + tr( "Click here to choose discrete progressions for this " + "automation pattern. The value of the connected " + "object will remain constant between control points " + "and be set immediately to the new value when each " + "control point is reached." ) ); + m_linearButton->setWhatsThis( + tr( "Click here to choose linear progressions for this " + "automation pattern. The value of the connected " + "object will change at a steady rate over time " + "between control points to reach the correct value at " + "each control point without a sudden change." ) ); + m_cubicHermiteButton->setWhatsThis( + tr( "Click here to choose cubic hermite progressions for this " + "automation pattern. The value of the connected " + "object will change in a smooth curve and ease in to " + "the peaks and valleys." ) ); + + + + // Copy paste buttons + + m_cutButton = new ToolButton( embed::getIconPixmap( "edit_cut" ), + tr( "Cut selected values (Ctrl+X)" ), + m_editor, SLOT( cutSelectedValues() ), + m_toolBar ); + + m_copyButton = new ToolButton( embed::getIconPixmap( "edit_copy" ), + tr( "Copy selected values (Ctrl+C)" ), + m_editor, SLOT( copySelectedValues() ), + m_toolBar ); + + m_pasteButton = new ToolButton( embed::getIconPixmap( "edit_paste" ), + tr( "Paste values from clipboard " + "(Ctrl+V)" ), + m_editor, SLOT( pasteValues() ), + m_toolBar ); + + m_cutButton->setWhatsThis( + tr( "Click here and selected values will be cut into the " + "clipboard. You can paste them anywhere in any pattern " + "by clicking on the paste button." ) ); + m_copyButton->setWhatsThis( + tr( "Click here and selected values will be copied into " + "the clipboard. You can paste them anywhere in any " + "pattern by clicking on the paste button." ) ); + m_pasteButton->setWhatsThis( + tr( "Click here and the values from the clipboard will be " + "pasted at the first visible measure." ) ); + + + + // Zoom controls + + QLabel * zoom_x_label = new QLabel( m_toolBar ); + zoom_x_label->setPixmap( embed::getIconPixmap( "zoom_x" ) ); + + m_zoomingXComboBox = new ComboBox( m_toolBar ); + m_zoomingXComboBox->setFixedSize( 80, 22 ); + + for( int i = 0; i < 6; ++i ) + { + m_editor->m_zoomingXModel.addItem( QString::number( 25 << i ) + "%" ); + } + m_editor->m_zoomingXModel.setValue( m_editor->m_zoomingXModel.findText( "100%" ) ); + + m_zoomingXComboBox->setModel( &m_editor->m_zoomingXModel ); + + connect( &m_editor->m_zoomingXModel, SIGNAL( dataChanged() ), + m_editor, SLOT( zoomingXChanged() ) ); + + + QLabel * zoom_y_label = new QLabel( m_toolBar ); + zoom_y_label->setPixmap( embed::getIconPixmap( "zoom_y" ) ); + + m_zoomingYComboBox = new ComboBox( m_toolBar ); + m_zoomingYComboBox->setFixedSize( 80, 22 ); + + m_editor->m_zoomingYModel.addItem( "Auto" ); + for( int i = 0; i < 7; ++i ) + { + m_editor->m_zoomingYModel.addItem( QString::number( 25 << i ) + "%" ); + } + m_editor->m_zoomingYModel.setValue( m_editor->m_zoomingYModel.findText( "Auto" ) ); + + m_zoomingYComboBox->setModel( &m_editor->m_zoomingYModel ); + + connect( &m_editor->m_zoomingYModel, SIGNAL( dataChanged() ), + m_editor, SLOT( zoomingYChanged() ) ); + + + + // Quantization controls + + QLabel * quantize_lbl = new QLabel( m_toolBar ); + quantize_lbl->setPixmap( embed::getIconPixmap( "quantize" ) ); + + m_quantizeComboBox = new ComboBox( m_toolBar ); + m_quantizeComboBox->setFixedSize( 60, 22 ); + + m_quantizeComboBox->setModel( &m_editor->m_quantizeModel ); + + + m_toolBar->addSeparator();; + m_toolBar->addWidget( m_drawButton ); + m_toolBar->addWidget( m_eraseButton ); + //m_toolBar->addWidget( m_selectButton ); + //m_toolBar->addWidget( m_moveButton ); + m_toolBar->addSeparator(); + m_toolBar->addWidget( m_discreteButton ); + m_toolBar->addWidget( m_linearButton ); + m_toolBar->addWidget( m_cubicHermiteButton ); + m_toolBar->addSeparator(); + m_toolBar->addWidget( new QLabel( tr("Tension: "), m_toolBar )); + m_toolBar->addWidget( m_tensionKnob ); + m_toolBar->addSeparator(); + m_toolBar->addWidget( m_cutButton ); + m_toolBar->addWidget( m_copyButton ); + m_toolBar->addWidget( m_pasteButton ); + m_toolBar->addSeparator(); + QWidget* timeLineButtons = new QWidget(); + timeLineButtons->setFixedHeight(m_cutButton->height()); + timeLineButtons->move(0,0); + QLayout* l = new QHBoxLayout( timeLineButtons ); + l->setSpacing(0); l->setMargin(0); + m_editor->m_timeLine->addToolButtons(timeLineButtons); + m_toolBar->addWidget(timeLineButtons); + m_toolBar->addSeparator(); + m_toolBar->addWidget( zoom_x_label ); + m_toolBar->addWidget( m_zoomingXComboBox ); + m_toolBar->addSeparator(); + m_toolBar->addWidget( zoom_y_label ); + m_toolBar->addWidget( m_zoomingYComboBox ); + m_toolBar->addSeparator(); + m_toolBar->addWidget( quantize_lbl ); + m_toolBar->addWidget( m_quantizeComboBox ); + + // Setup our actual window + setFocusPolicy( Qt::StrongFocus ); + setFocus(); + setWindowIcon( embed::getIconPixmap( "automation" ) ); + + // Add us to workspace + if( Engine::mainWindow()->workspace() ) + { + Engine::mainWindow()->workspace()->addSubWindow( this ); + parentWidget()->resize( INITIAL_WIDTH, INITIAL_HEIGHT ); + parentWidget()->move( 5, 5 ); + parentWidget()->hide(); + } + else + { + resize( INITIAL_WIDTH, INITIAL_HEIGHT ); + hide(); + } +} + + +AutomationEditorWindow::~AutomationEditorWindow() +{ +} + + +void AutomationEditorWindow::setCurrentPattern(AutomationPattern* pattern) +{ + m_editor->setCurrentPattern(pattern); + + if (pattern == nullptr) + return; + + switch(m_editor->m_pattern->progressionType()) + { + case AutomationPattern::DiscreteProgression: + m_discreteButton->setChecked(true); + break; + case AutomationPattern::LinearProgression: + m_linearButton->setChecked(true); + break; + case AutomationPattern::CubicHermiteProgression: + m_cubicHermiteButton->setChecked(true); + break; + } + + emit currentPatternChanged(); +} + + +const AutomationPattern* AutomationEditorWindow::currentPattern() +{ + return m_editor->currentPattern(); +} + + +int AutomationEditorWindow::quantization() const +{ + return m_editor->quantization(); +} + +void AutomationEditorWindow::closeEvent(QCloseEvent* _ce) +{ + QApplication::restoreOverrideCursor(); + if( parentWidget() ) + { + parentWidget()->hide(); + } + else + { + hide(); + } + _ce->ignore(); +} + +void AutomationEditorWindow::play() +{ + m_editor->play(); + setPauseIcon(Engine::getSong()->isPlaying()); +} + +void AutomationEditorWindow::stop() +{ + m_editor->stop(); +} diff --git a/src/gui/AutomationPatternView.cpp b/src/gui/AutomationPatternView.cpp index 17fbb559f..fba27ceb1 100644 --- a/src/gui/AutomationPatternView.cpp +++ b/src/gui/AutomationPatternView.cpp @@ -125,7 +125,7 @@ void AutomationPatternView::disconnectObject( QAction * _a ) //If automation editor is opened, update its display after disconnection if( Engine::automationEditor() ) { - Engine::automationEditor()->updateAfterPatternChange(); + Engine::automationEditor()->m_editor->updateAfterPatternChange(); } //if there is no more connection connected to the AutomationPattern diff --git a/src/gui/Editor.cpp b/src/gui/Editor.cpp index 8f0e80da2..e292ced1b 100644 --- a/src/gui/Editor.cpp +++ b/src/gui/Editor.cpp @@ -30,13 +30,13 @@ #include -void Editor::setPlaying(bool playing) +void Editor::setPauseIcon(bool displayPauseIcon) { // If we're playing, show a pause icon - if (playing) - m_playButton->setIcon(embed::getIconPixmap("play")); - else + if (displayPauseIcon) m_playButton->setIcon(embed::getIconPixmap("pause")); + else + m_playButton->setIcon(embed::getIconPixmap("play")); } Editor::Editor(bool record) :