diff --git a/ChangeLog b/ChangeLog index 929c07efe..d0d52d537 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-12-11 Tobias Doerffel + + * include/automation_pattern.h: + * src/core/automation_pattern.cpp: + do not disable automation when just editing first point of an + automation pattern (closes #2146230) + + * include/automation_pattern_view.h: + * src/gui/automation_pattern_view.cpp: + splitted view component out of automation_pattern.* + 2008-12-10 Tobias Doerffel * plugins/vst_base/communication.h: diff --git a/include/automation_pattern.h b/include/automation_pattern.h index 28ca99a41..49eedeaa5 100644 --- a/include/automation_pattern.h +++ b/include/automation_pattern.h @@ -123,44 +123,4 @@ private: } ; - -class automationPatternView : public trackContentObjectView -{ - Q_OBJECT -public: - automationPatternView( automationPattern * _pat, trackView * _parent ); - virtual ~automationPatternView(); - - -public slots: - virtual void update( void ); - - -protected slots: - void resetName( void ); - void changeName( void ); - void disconnectObject( QAction * _a ); - - -protected: - virtual void constructContextMenu( QMenu * ); - virtual void mouseDoubleClickEvent( QMouseEvent * _me ); - virtual void paintEvent( QPaintEvent * _pe ); - virtual void resizeEvent( QResizeEvent * _re ) - { - m_needsUpdate = true; - trackContentObjectView::resizeEvent( _re ); - } - virtual void dragEnterEvent( QDragEnterEvent * _dee ); - virtual void dropEvent( QDropEvent * _de ); - - -private: - automationPattern * m_pat; - QPixmap m_paintPixmap; - bool m_needsUpdate; - -} ; - - #endif diff --git a/src/core/automation_pattern.cpp b/src/core/automation_pattern.cpp index da1c477af..fe473ebb0 100644 --- a/src/core/automation_pattern.cpp +++ b/src/core/automation_pattern.cpp @@ -30,20 +30,12 @@ #include #include "automation_pattern.h" -#include "automation_track.h" +#include "automation_pattern_view.h" #include "automation_editor.h" -#include "bb_track_container.h" -#include "embed.h" -#include "engine.h" -#include "gui_templates.h" -#include "note.h" +#include "automation_track.h" #include "project_journal.h" -#include "rename_dialog.h" +#include "bb_track_container.h" #include "song.h" -#include "string_pair_drag.h" -#include "templates.h" -#include "tooltip.h" -#include "track_container.h" @@ -161,20 +153,15 @@ midiTime automationPattern::putValue( const midiTime & _time, const float _value, const bool _quant_pos ) { - midiTime new_time = _quant_pos && engine::getAutomationEditor() ? + midiTime newTime = _quant_pos && engine::getAutomationEditor() ? note::quantized( _time, engine::getAutomationEditor()->quantization() ) : _time; - m_timeMap[new_time] = _value; + m_timeMap[newTime] = _value; - if( new_time != 0 ) + if( newTime == 0 ) { - m_hasAutomation = true; - } - else - { - m_hasAutomation = false; for( objectVector::iterator it = m_objects.begin(); it != m_objects.end(); ) { @@ -190,6 +177,29 @@ midiTime automationPattern::putValue( const midiTime & _time, } } + // just one automation value? + if( m_timeMap.size() == 1 ) + { + m_hasAutomation = m_objects.isEmpty(); // usually false + for( objectVector::iterator it = m_objects.begin(); + it != m_objects.end(); ++it ) + { + // default value differs from current value? + if( *it && _value != ( *it )->initValue() ) + { + // then enable automating this object + m_hasAutomation = true; + } + } + } + else + { + // in all other cases assume we have automation + m_hasAutomation = true; + } + + // we need to maximize our length in case we're part of a hidden + // automation track as the user can't resize this pattern if( getTrack() && getTrack()->type() == track::HiddenAutomationTrack ) { changeLength( length() ); @@ -197,7 +207,7 @@ midiTime automationPattern::putValue( const midiTime & _time, emit dataChanged(); - return new_time; + return newTime; } @@ -209,15 +219,20 @@ void automationPattern::removeValue( const midiTime & _time ) { m_timeMap.remove( _time ); - if( m_timeMap.size() <= 1 ) + if( m_timeMap.size() == 1 ) { + const float val = m_timeMap[0]; m_hasAutomation = false; for( objectVector::iterator it = m_objects.begin(); it != m_objects.end(); ) { if( *it ) { - ( *it )->setValue( m_timeMap[0] ); + ( *it )->setValue( val ); + if( ( *it )->initValue() != val ) + { + m_hasAutomation = true; + } ++it; } else @@ -272,7 +287,7 @@ void automationPattern::saveSettings( QDomDocument & _doc, QDomElement & _this ) for( objectVector::const_iterator it = m_objects.begin(); it != m_objects.end(); ++it ) { - if( *it != NULL ) + if( *it ) { QDomElement element = _doc.createElement( "object" ); element.setAttribute( "id", ( *it )->id() ); @@ -522,301 +537,5 @@ void automationPattern::objectDestroyed( jo_id_t _id ) - -automationPatternView::automationPatternView( automationPattern * _pattern, - trackView * _parent ) : - trackContentObjectView( _pattern, _parent ), - m_pat( _pattern ), - m_paintPixmap(), - m_needsUpdate( true ) -{ - connect( m_pat, SIGNAL( dataChanged() ), - this, SLOT( update() ) ); - - setAttribute( Qt::WA_OpaquePaintEvent, true ); - setFixedHeight( parentWidget()->height() - 2 ); - setAutoResizeEnabled( false ); - - toolTip::add( this, tr( "double-click to open this pattern in " - "automation editor" ) ); -} - - - - -automationPatternView::~automationPatternView() -{ -} - - - - - -void automationPatternView::update( void ) -{ - m_needsUpdate = true; - if( fixedTCOs() ) - { - m_pat->changeLength( m_pat->length() ); - } - trackContentObjectView::update(); -} - - - - -void automationPatternView::resetName( void ) -{ - m_pat->setName( QString::null ); -} - - - - -void automationPatternView::changeName( void ) -{ - QString s = m_pat->name(); - renameDialog rename_dlg( s ); - rename_dlg.exec(); - m_pat->setName( s ); - update(); -} - - - - -void automationPatternView::disconnectObject( QAction * _a ) -{ - journallingObject * j = engine::getProjectJournal()-> - getJournallingObject( _a->data().toInt() ); - if( j && dynamic_cast( j ) ) - { - m_pat->m_objects.erase( qFind( m_pat->m_objects.begin(), - m_pat->m_objects.end(), - dynamic_cast( j ) ) ); - update(); - } -} - - - - -void automationPatternView::constructContextMenu( QMenu * _cm ) -{ - QAction * a = new QAction( embed::getIconPixmap( "automation" ), - tr( "Open in Automation editor" ), _cm ); - _cm->insertAction( _cm->actions()[0], a ); - connect( a, SIGNAL( triggered( bool ) ), - m_pat, SLOT( openInAutomationEditor() ) ); - _cm->insertSeparator( _cm->actions()[1] ); - - _cm->addSeparator(); - - _cm->addAction( embed::getIconPixmap( "edit_erase" ), - tr( "Clear" ), m_pat, SLOT( clear() ) ); - _cm->addSeparator(); - - _cm->addAction( embed::getIconPixmap( "reload" ), tr( "Reset name" ), - this, SLOT( resetName() ) ); - _cm->addAction( embed::getIconPixmap( "edit_rename" ), - tr( "Change name" ), - this, SLOT( changeName() ) ); - if( !m_pat->m_objects.isEmpty() ) - { - _cm->addSeparator(); - QMenu * m = new QMenu( tr( "%1 Connections" ). - arg( m_pat->m_objects.count() ), _cm ); - for( automationPattern::objectVector::iterator it = - m_pat->m_objects.begin(); - it != m_pat->m_objects.end(); ++it ) - { - if( *it ) - { - a = new QAction( tr( "Disconnect \"%1\"" ). - arg( ( *it )->fullDisplayName() ), m ); - a->setData( ( *it )->id() ); - m->addAction( a ); - } - } - connect( m, SIGNAL( triggered( QAction * ) ), - this, SLOT( disconnectObject( QAction * ) ) ); - _cm->addMenu( m ); - } - - _cm->addSeparator(); -} - - - - -void automationPatternView::mouseDoubleClickEvent( QMouseEvent * _me ) -{ - if( _me->button() != Qt::LeftButton ) - { - _me->ignore(); - return; - } - m_pat->openInAutomationEditor(); -} - - - - -void automationPatternView::paintEvent( QPaintEvent * ) -{ - if( m_needsUpdate == false ) - { - QPainter p( this ); - p.drawPixmap( 0, 0, m_paintPixmap ); - return; - } - - m_needsUpdate = false; - - if( m_paintPixmap.isNull() == true || m_paintPixmap.size() != size() ) - { - m_paintPixmap = QPixmap( size() ); - } - - QPainter p( &m_paintPixmap ); - - QLinearGradient lingrad( 0, 0, 0, height() ); - const QColor c = isSelected() ? QColor( 0, 0, 224 ) : - QColor( 96, 96, 96 ); - lingrad.setColorAt( 0, c ); - lingrad.setColorAt( 0.5, Qt::black ); - lingrad.setColorAt( 1, c ); - p.setBrush( lingrad ); - p.setPen( QColor( 0, 0, 0 ) ); - p.drawRect( QRect( 0, 0, width() - 1, height() - 1 ) ); - - const float ppt = fixedTCOs() ? - ( parentWidget()->width() - 2 * TCO_BORDER_WIDTH ) - / (float) m_pat->length().getTact() : - pixelsPerTact(); - - const int x_base = TCO_BORDER_WIDTH; - p.setPen( QColor( 0, 0, 0 ) ); - - for( tact t = 1; t < m_pat->length().getTact(); ++t ) - { - p.drawLine( x_base + static_cast( ppt * t ) - 1, - TCO_BORDER_WIDTH, x_base + static_cast( - ppt * t ) - 1, 5 ); - p.drawLine( x_base + static_cast( ppt * t ) - 1, - height() - ( 4 + 2 * TCO_BORDER_WIDTH ), - x_base + static_cast( ppt * t ) - 1, - height() - 2 * TCO_BORDER_WIDTH ); - } - - const float min = m_pat->firstObject()->minValue(); - const float max = m_pat->firstObject()->maxValue(); - - const float y_scale = max - min; - const float h = ( height()-2*TCO_BORDER_WIDTH ) / y_scale; - - p.translate( 0.0f, max * height() / y_scale-1 ); - p.scale( 1.0f, -h ); - - QLinearGradient lin2grad( 0, min, 0, max ); - const QColor cl = QColor( 255, 224, 0 ); - const QColor cd = QColor( 229, 158, 0 ); - - lin2grad.setColorAt( 1, cl ); - lin2grad.setColorAt( 0, cd ); - - for( automationPattern::timeMap::const_iterator it = - m_pat->getTimeMap().begin(); - it != m_pat->getTimeMap().end(); ++it ) - { - const float x1 = 2 * x_base + it.key() * ppt / - midiTime::ticksPerTact(); - float x2; - if( it+1 != m_pat->getTimeMap().end() ) - { - x2 = (it+1).key() * ppt / midiTime::ticksPerTact() + 2; - } - else - { - x2 = (float)( width() - TCO_BORDER_WIDTH ); - } - p.fillRect( QRectF( x1, 0.0f, x2-x1, it.value() ), - lin2grad ); - } - - p.resetMatrix(); - p.setFont( pointSize<7>( p.font() ) ); - if( m_pat->isMuted() || m_pat->getTrack()->isMuted() ) - { - p.setPen( QColor( 192, 192, 192 ) ); - } - else - { - p.setPen( QColor( 0, 64, 255 ) ); - } - - p.drawText( 2, p.fontMetrics().height() - 1, m_pat->name() ); - - if( m_pat->isMuted() ) - { - p.drawPixmap( 3, p.fontMetrics().height() + 1, - embed::getIconPixmap( "muted", 16, 16 ) ); - } - - p.end(); - - p.begin( this ); - p.drawPixmap( 0, 0, m_paintPixmap ); - -} - - - - -void automationPatternView::dragEnterEvent( QDragEnterEvent * _dee ) -{ - stringPairDrag::processDragEnterEvent( _dee, "automatable_model" ); - if( !_dee->isAccepted() ) - { - trackContentObjectView::dragEnterEvent( _dee ); - } -} - - - - -void automationPatternView::dropEvent( QDropEvent * _de ) -{ - QString type = stringPairDrag::decodeKey( _de ); - QString val = stringPairDrag::decodeValue( _de ); - if( type == "automatable_model" ) - { - automatableModel * mod = dynamic_cast( - engine::getProjectJournal()-> - getJournallingObject( val.toInt() ) ); - if( mod != NULL ) - { - m_pat->addObject( mod ); - } - update(); - - if( engine::getAutomationEditor() && - engine::getAutomationEditor()->currentPattern() == - m_pat ) - { - engine::getAutomationEditor()->setCurrentPattern( - m_pat ); - } - } - else - { - trackContentObjectView::dropEvent( _de ); - } -} - - - - - #include "moc_automation_pattern.cxx"