void PatternView::wheelEvent( QWheelEvent * _we ) { if( m_pat->m_patternType == Pattern::BeatPattern && ( fixedTCOs() || pixelsPerTact() >= 96 || m_pat->m_steps != MidiTime::stepsPerTact() ) && _we->y() > height() - s_stepBtnOff->height() ) { // get the step number that was wheeled on and // do calculations in floats to prevent rounding errors... float tmp = ( ( float(_we->x()) - TCO_BORDER_WIDTH ) * float( m_pat -> m_steps ) ) / float(width() - TCO_BORDER_WIDTH*2); int step = int( tmp ); if( step >= m_pat->m_steps ) { return; } int vol = 0; int len = 0; Note * n = m_pat->noteAtStep( step ); if( n != NULL ) { vol = n->getVolume(); len = n->length(); if( len == 0 && _we->delta() > 0 ) { n->setLength( -DefaultTicksPerTact ); n->setVolume( 5 ); } else if( _we->delta() > 0 ) { n->setVolume( qMin( 100, vol + 5 ) ); } else { n->setVolume( qMax( 0, vol - 5 ) ); } Engine::getSong()->setModified(); update(); if( gui->pianoRoll()->currentPattern() == m_pat ) { gui->pianoRoll()->update(); } } _we->accept(); } else { TrackContentObjectView::wheelEvent( _we ); } }
void PatternView::mouseDoubleClickEvent(QMouseEvent *_me) { if( _me->button() != Qt::LeftButton ) { _me->ignore(); return; } if( !fixedTCOs() ) { openInPianoRoll(); } }
void patternView::mousePressEvent( QMouseEvent * _me ) { if( _me->button() == Qt::LeftButton && m_pat->m_patternType == pattern::BeatPattern && ( fixedTCOs() || pixelsPerTact() >= 96 || m_pat->m_steps != MidiTime::stepsPerTact() ) && _me->y() > height() - s_stepBtnOff->height() ) { int step = ( _me->x() - TCO_BORDER_WIDTH ) * m_pat->length() / DefaultBeatsPerTact / width(); if( step >= m_pat->m_steps ) { return; } note * n = m_pat->m_notes[step]; if( n->length() < 0 ) { n->setLength( 0 ); } else { n->setLength( -DefaultTicksPerTact ); } engine::getSong()->setModified(); update(); if( engine::getPianoRoll()->currentPattern() == m_pat ) { engine::getPianoRoll()->update(); } } else if( m_pat->m_frozenPattern != NULL && _me->button() == Qt::LeftButton && _me->modifiers() & Qt::ShiftModifier ) { QString s; new stringPairDrag( "sampledata", m_pat->m_frozenPattern->toBase64( s ), embed::getIconPixmap( "freeze" ), this ); } else { trackContentObjectView::mousePressEvent( _me ); } }
void SampleTCOView::contextMenuEvent( QContextMenuEvent * _cme ) { if( _cme->modifiers() ) { return; } QMenu contextMenu( this ); if( fixedTCOs() == false ) { contextMenu.addAction( embed::getIconPixmap( "cancel" ), tr( "Delete (middle mousebutton)" ), this, SLOT( remove() ) ); contextMenu.addSeparator(); contextMenu.addAction( embed::getIconPixmap( "edit_cut" ), tr( "Cut" ), this, SLOT( cut() ) ); } contextMenu.addAction( embed::getIconPixmap( "edit_copy" ), tr( "Copy" ), m_tco, SLOT( copy() ) ); contextMenu.addAction( embed::getIconPixmap( "edit_paste" ), tr( "Paste" ), m_tco, SLOT( paste() ) ); contextMenu.addSeparator(); contextMenu.addAction( embed::getIconPixmap( "muted" ), tr( "Mute/unmute (<%1> + middle click)" ).arg( #ifdef LMMS_BUILD_APPLE "⌘"), #else "Ctrl"), #endif m_tco, SLOT( toggleMute() ) ); /*contextMenu.addAction( embed::getIconPixmap( "record" ), tr( "Set/clear record" ), m_tco, SLOT( toggleRecord() ) );*/ constructContextMenu( &contextMenu ); contextMenu.exec( QCursor::pos() ); }
void PatternView::paintEvent( QPaintEvent * ) { if( m_needsUpdate == false ) { QPainter p( this ); p.drawPixmap( 0, 0, m_paintPixmap ); return; } QPainter _p( this ); const QColor styleColor = _p.pen().brush().color(); m_pat->changeLength( m_pat->length() ); 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() ); QColor c; if(( m_pat->m_patternType != Pattern::BeatPattern ) && !( m_pat->getTrack()->isMuted() || m_pat->isMuted() )) { c = styleColor; } else { c = QColor( 80, 80, 80 ); } if( isSelected() == true ) { c.setRgb( qMax( c.red() - 128, 0 ), qMax( c.green() - 128, 0 ), 255 ); } if( m_pat->m_patternType != Pattern::BeatPattern ) { lingrad.setColorAt( 1, c.darker( 300 ) ); lingrad.setColorAt( 0, c ); } else { lingrad.setColorAt( 0, c.darker( 300 ) ); lingrad.setColorAt( 1, c ); } p.setBrush( lingrad ); if( gui->pianoRoll()->currentPattern() == m_pat && m_pat->m_patternType != Pattern::BeatPattern ) p.setPen( c.lighter( 130 ) ); else p.setPen( c.darker( 300 ) ); p.drawRect( QRect( 0, 0, width() - 1, height() - 1 ) ); p.setBrush( QBrush() ); if( m_pat->m_patternType != Pattern::BeatPattern ) { if( gui->pianoRoll()->currentPattern() == m_pat ) p.setPen( c.lighter( 160 ) ); else p.setPen( c.lighter( 130 ) ); p.drawRect( QRect( 1, 1, width() - 3, height() - 3 ) ); } const float ppt = fixedTCOs() ? ( parentWidget()->width() - 2 * TCO_BORDER_WIDTH ) / (float) m_pat->length().getTact() : ( width() - 2 * TCO_BORDER_WIDTH ) / (float) m_pat->length().getTact(); const int x_base = TCO_BORDER_WIDTH; p.setPen( c.darker( 300 ) ); for( tact_t t = 1; t < m_pat->length().getTact(); ++t ) { p.drawLine( x_base + static_cast<int>( ppt * t ) - 1, TCO_BORDER_WIDTH, x_base + static_cast<int>( ppt * t ) - 1, 5 ); p.drawLine( x_base + static_cast<int>( ppt * t ) - 1, height() - ( 4 + 2 * TCO_BORDER_WIDTH ), x_base + static_cast<int>( ppt * t ) - 1, height() - 2 * TCO_BORDER_WIDTH ); } // melody pattern paint event if( m_pat->m_patternType == Pattern::MelodyPattern ) { if( m_pat->m_notes.size() > 0 ) { // first determine the central tone so that we can // display the area where most of the m_notes are // also calculate min/max tones so the tonal range can be // properly stretched accross the pattern vertically int central_key = 0; int max_key = 0; int min_key = 9999999; int total_notes = 0; for( NoteVector::Iterator it = m_pat->m_notes.begin(); it != m_pat->m_notes.end(); ++it ) { if( ( *it )->length() > 0 ) { max_key = qMax( max_key, ( *it )->key() ); min_key = qMin( min_key, ( *it )->key() ); central_key += ( *it )->key(); ++total_notes; } } if( total_notes > 0 ) { central_key = central_key / total_notes; const int keyrange = qMax( qMax( max_key - central_key, central_key - min_key ), 1 ); // debug code // qDebug( "keyrange: %d", keyrange ); // determine height of the pattern view, sans borders const int ht = (height() - 1 - TCO_BORDER_WIDTH * 2) -1; // determine maximum height value for drawing bounds checking const int max_ht = height() - 1 - TCO_BORDER_WIDTH; // set colour based on mute status if( m_pat->getTrack()->isMuted() || m_pat->isMuted() ) { p.setPen( QColor( 160, 160, 160 ) ); } else { p.setPen( fgColor() ); } // scan through all the notes and draw them on the pattern for( NoteVector::Iterator it = m_pat->m_notes.begin(); it != m_pat->m_notes.end(); ++it ) { // calculate relative y-position const float y_key = ( float( central_key - ( *it )->key() ) / keyrange + 1.0f ) / 2; // multiply that by pattern height const int y_pos = static_cast<int>( TCO_BORDER_WIDTH + y_key * ht ) + 1; // debug code // if( ( *it )->length() > 0 ) qDebug( "key %d, central_key %d, y_key %f, y_pos %d", ( *it )->key(), central_key, y_key, y_pos ); // check that note isn't out of bounds, and has a length if( ( *it )->length() > 0 && y_pos >= TCO_BORDER_WIDTH && y_pos <= max_ht ) { // calculate start and end x-coords of the line to be drawn const int x1 = x_base + static_cast<int> ( ( *it )->pos() * ( ppt / MidiTime::ticksPerTact() ) ); const int x2 = x_base + static_cast<int> ( ( ( *it )->pos() + ( *it )->length() ) * ( ppt / MidiTime::ticksPerTact() ) ); // check bounds, draw line if( x1 < width() - TCO_BORDER_WIDTH ) p.drawLine( x1, y_pos, qMin( x2, width() - TCO_BORDER_WIDTH ), y_pos ); } } } } } // beat pattern paint event else if( m_pat->m_patternType == Pattern::BeatPattern && ( fixedTCOs() || ppt >= 96 || m_pat->m_steps != MidiTime::stepsPerTact() ) ) { QPixmap stepon; QPixmap stepoverlay; QPixmap stepoff; QPixmap stepoffl; const int steps = qMax( 1, m_pat->m_steps ); const int w = width() - 2 * TCO_BORDER_WIDTH; // scale step graphics to fit the beat pattern length stepon = s_stepBtnOn->scaled( w / steps, s_stepBtnOn->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); stepoverlay = s_stepBtnOverlay->scaled( w / steps, s_stepBtnOn->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); stepoff = s_stepBtnOff->scaled( w / steps, s_stepBtnOff->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); stepoffl = s_stepBtnOffLight->scaled( w / steps, s_stepBtnOffLight->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); for( int it = 0; it < steps; it++ ) // go through all the steps in the beat pattern { Note * n = m_pat->noteAtStep( it ); // figure out x and y coordinates for step graphic const int x = TCO_BORDER_WIDTH + static_cast<int>( it * w / steps ); const int y = height() - s_stepBtnOff->height() - 1; // get volume and length of note, if noteAtStep returned null // (meaning, note at step doesn't exist for some reason) // then set both at zero, ie. treat as an off step const int vol = ( n != NULL ? n->getVolume() : 0 ); const int len = ( n != NULL ? int( n->length() ) : 0 ); if( len < 0 ) { p.drawPixmap( x, y, stepoff ); for( int i = 0; i < vol / 5 + 1; ++i ) { p.drawPixmap( x, y, stepon ); } for( int i = 0; i < ( 25 + ( vol - 75 ) ) / 5; ++i ) { p.drawPixmap( x, y, stepoverlay ); } } else if( ( it / 4 ) % 2 ) { p.drawPixmap( x, y, stepoffl ); } else { p.drawPixmap( x, y, stepoff ); } } // end for loop } p.setFont( pointSize<8>( p.font() ) ); QColor text_color = ( m_pat->isMuted() || m_pat->getTrack()->isMuted() ) ? QColor( 30, 30, 30 ) : textColor(); if( m_pat->name() != m_pat->instrumentTrack()->name() ) { p.setPen( QColor( 0, 0, 0 ) ); p.drawText( 4, p.fontMetrics().height()+1, m_pat->name() ); p.setPen( text_color ); p.drawText( 3, p.fontMetrics().height(), m_pat->name() ); } if( m_pat->isMuted() ) { p.drawPixmap( 3, p.fontMetrics().height() + 1, embed::getIconPixmap( "muted", 16, 16 ) ); } p.end(); _p.drawPixmap( 0, 0, m_paintPixmap ); }
void PatternView::mousePressEvent( QMouseEvent * _me ) { if( _me->button() == Qt::LeftButton && m_pat->m_patternType == Pattern::BeatPattern && ( fixedTCOs() || pixelsPerTact() >= 96 || m_pat->m_steps != MidiTime::stepsPerTact() ) && _me->y() > height() - s_stepBtnOff->height() ) // when mouse button is pressed in beat/bassline -mode { // get the step number that was clicked on and // do calculations in floats to prevent rounding errors... float tmp = ( ( float(_me->x()) - TCO_BORDER_WIDTH ) * float( m_pat -> m_steps ) ) / float(width() - TCO_BORDER_WIDTH*2); int step = int( tmp ); // debugging to ensure we get the correct step... // qDebug( "Step (%f) %d", tmp, step ); if( step >= m_pat->m_steps ) { qDebug( "Something went wrong in pattern.cpp: step %d doesn't exist in pattern!", step ); return; } Note * n = m_pat->noteAtStep( step ); // if note at step not found, ensureBeatNotes and try again if( n == NULL ) { m_pat -> ensureBeatNotes(); n = m_pat->noteAtStep( step ); if( n == NULL ) // still can't find a note? bail! { qDebug( "Something went wrong in pattern.cpp: couldn't add note at step %d!", step ); return; } } else // note at step found { m_pat->addJournalCheckPoint(); if( n->length() < 0 ) { n->setLength( 0 ); // set note as enabled beat note } else { n->setLength( -DefaultTicksPerTact ); // set note as disabled beat note } } Engine::getSong()->setModified(); update(); if( gui->pianoRoll()->currentPattern() == m_pat ) { gui->pianoRoll()->update(); } } else // if not in beat/bassline -mode, let parent class handle the event { TrackContentObjectView::mousePressEvent( _me ); } }
void patternView::paintEvent( QPaintEvent * ) { if( m_needsUpdate == false ) { QPainter p( this ); p.drawPixmap( 0, 0, m_paintPixmap ); return; } m_pat->changeLength( m_pat->length() ); 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, QColor( 16, 16, 16 ) ); lingrad.setColorAt( 0.5, c ); lingrad.setColorAt( 1, QColor( 16, 16, 16 ) ); p.setBrush( lingrad ); p.setPen( QColor( 0, 0, 0 ) ); //p.drawRect( 0, 0, width() - 1, height() - 1 ); 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 t = 1; t < m_pat->length().getTact(); ++t ) { p.drawLine( x_base + static_cast<int>( ppt * t ) - 1, TCO_BORDER_WIDTH, x_base + static_cast<int>( ppt * t ) - 1, 5 ); p.drawLine( x_base + static_cast<int>( ppt * t ) - 1, height() - ( 4 + 2 * TCO_BORDER_WIDTH ), x_base + static_cast<int>( ppt * t ) - 1, height() - 2 * TCO_BORDER_WIDTH ); } if( m_pat->m_patternType == pattern::MelodyPattern ) { int central_key = 0; if( m_pat->m_notes.size() > 0 ) { // first determine the central tone so that we can // display the area where most of the m_notes are int total_notes = 0; for( NoteVector::Iterator it = m_pat->m_notes.begin(); it != m_pat->m_notes.end(); ++it ) { if( ( *it )->length() > 0 ) { central_key += ( *it )->key(); ++total_notes; } } if( total_notes > 0 ) { central_key = central_key / total_notes; const int central_y = height() / 2; int y_base = central_y + TCO_BORDER_WIDTH -1; if( m_pat->getTrack()->isMuted() || m_pat->isMuted() ) { p.setPen( QColor( 160, 160, 160 ) ); } else if( m_pat->m_frozenPattern != NULL ) { p.setPen( QColor( 0x70, 0xFF, 0xFF ) ); } else { p.setPen( QColor( 0x77, 0xC7, 0xD8 ) ); } for( NoteVector::Iterator it = m_pat->m_notes.begin(); it != m_pat->m_notes.end(); ++it ) { const int y_pos = central_key - ( *it )->key(); if( ( *it )->length() > 0 && y_pos > -central_y && y_pos < central_y ) { const int x1 = 2 * x_base + static_cast<int>( ( *it )->pos() * ppt / MidiTime::ticksPerTact() ); const int x2 = static_cast<int>( ( ( *it )->pos() + ( *it )->length() ) * ppt / MidiTime::ticksPerTact() ); p.drawLine( x1, y_base + y_pos, x2, y_base + y_pos ); } } } } } else if( m_pat->m_patternType == pattern::BeatPattern && ( fixedTCOs() || ppt >= 96 || m_pat->m_steps != MidiTime::stepsPerTact() ) ) { QPixmap stepon; QPixmap stepoverlay; QPixmap stepoff; QPixmap stepoffl; const int steps = qMax( 1, m_pat->length() / DefaultBeatsPerTact ); const int w = width() - 2 * TCO_BORDER_WIDTH; stepon = s_stepBtnOn->scaled( w / steps, s_stepBtnOn->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); stepoverlay = s_stepBtnOverlay->scaled( w / steps, s_stepBtnOn->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); stepoff = s_stepBtnOff->scaled( w / steps, s_stepBtnOff->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); stepoffl = s_stepBtnOffLight->scaled( w / steps, s_stepBtnOffLight->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); for( NoteVector::Iterator it = m_pat->m_notes.begin(); it != m_pat->m_notes.end(); ++it ) { const int no = ( *it )->pos() / DefaultBeatsPerTact; const int x = TCO_BORDER_WIDTH + static_cast<int>( no * w / steps ); const int y = height() - s_stepBtnOff->height() - 1; const int vol = ( *it )->getVolume(); if( ( *it )->length() < 0 ) { p.drawPixmap( x, y, stepoff ); for( int i = 0; i < vol / 5 + 1; ++i ) { p.drawPixmap( x, y, stepon ); } for( int i = 0; i < ( 25 + ( vol - 75 ) ) / 5; ++i ) { p.drawPixmap( x, y, stepoverlay ); } } else if( ( no / 4 ) % 2 ) { p.drawPixmap( x, y, stepoff ); } else { p.drawPixmap( x, y, stepoffl ); } } } p.setFont( pointSize<8>( p.font() ) ); if( m_pat->isMuted() || m_pat->getTrack()->isMuted() ) { p.setPen( QColor( 192, 192, 192 ) ); } else { p.setPen( QColor( 32, 240, 101 ) ); } if( m_pat->name() != m_pat->instrumentTrack()->name() ) { 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 ) ); } else if( m_pat->m_frozenPattern != NULL ) { p.setBrush( QBrush() ); p.setPen( QColor( 0x70, 255, 255 ) ); p.drawRect( 0, 0, width()-1, height() - 1 ); p.drawPixmap( 3, height() - s_frozen->height() - 4, *s_frozen ); } p.end(); p.begin( this ); p.drawPixmap( 0, 0, m_paintPixmap ); }
void SampleTCOView::paintEvent( QPaintEvent * pe ) { QPainter painter( this ); if( !needsUpdate() ) { painter.drawPixmap( 0, 0, m_paintPixmap ); return; } setNeedsUpdate( false ); if (m_paintPixmap.isNull() || m_paintPixmap.size() != size()) { m_paintPixmap = QPixmap(size()); } QPainter p( &m_paintPixmap ); QLinearGradient lingrad( 0, 0, 0, height() ); QColor c; bool muted = m_tco->getTrack()->isMuted() || m_tco->isMuted(); // state: selected, muted, normal c = isSelected() ? selectedColor() : ( muted ? mutedBackgroundColor() : painter.background().color() ); lingrad.setColorAt( 1, c.darker( 300 ) ); lingrad.setColorAt( 0, c ); // paint a black rectangle under the pattern to prevent glitches with transparent backgrounds p.fillRect( rect(), QColor( 0, 0, 0 ) ); if( gradient() ) { p.fillRect( rect(), lingrad ); } else { p.fillRect( rect(), c ); } p.setPen( !muted ? painter.pen().brush().color() : mutedColor() ); const int spacing = TCO_BORDER_WIDTH + 1; const float ppt = fixedTCOs() ? ( parentWidget()->width() - 2 * TCO_BORDER_WIDTH ) / (float) m_tco->length().getTact() : pixelsPerTact(); float nom = Engine::getSong()->getTimeSigModel().getNumerator(); float den = Engine::getSong()->getTimeSigModel().getDenominator(); float ticksPerTact = DefaultTicksPerTact * nom / den; float offset = m_tco->startTimeOffset() / ticksPerTact * pixelsPerTact(); QRect r = QRect( TCO_BORDER_WIDTH + offset, spacing, qMax( static_cast<int>( m_tco->sampleLength() * ppt / ticksPerTact ), 1 ), rect().bottom() - 2 * spacing ); m_tco->m_sampleBuffer->visualize( p, r, pe->rect() ); QFileInfo fileInfo(m_tco->m_sampleBuffer->audioFile()); QString filename = fileInfo.fileName(); paintTextLabel(filename, p); // disable antialiasing for borders, since its not needed p.setRenderHint( QPainter::Antialiasing, false ); // inner border p.setPen( c.lighter( 160 ) ); p.drawRect( 1, 1, rect().right() - TCO_BORDER_WIDTH, rect().bottom() - TCO_BORDER_WIDTH ); // outer border p.setPen( c.darker( 300 ) ); p.drawRect( 0, 0, rect().right(), rect().bottom() ); // draw the 'muted' pixmap only if the pattern was manualy muted if( m_tco->isMuted() ) { const int spacing = TCO_BORDER_WIDTH; const int size = 14; p.drawPixmap( spacing, height() - ( size + spacing ), embed::getIconPixmap( "muted", size, size ) ); } // recording sample tracks is not possible at the moment /* if( m_tco->isRecord() ) { p.setFont( pointSize<7>( p.font() ) ); p.setPen( textShadowColor() ); p.drawText( 10, p.fontMetrics().height()+1, "Rec" ); p.setPen( textColor() ); p.drawText( 9, p.fontMetrics().height(), "Rec" ); p.setBrush( QBrush( textColor() ) ); p.drawEllipse( 4, 5, 4, 4 ); }*/ p.end(); painter.drawPixmap( 0, 0, m_paintPixmap ); }