void SongEditorPatternList::patternPopup_copy() { Engine *pEngine = g_engine; T<Song>::shared_ptr pSong = pEngine->getSong(); PatternList *pPatternList = pSong->get_pattern_list(); int nSelectedPattern = pEngine->getSelectedPatternNumber(); T<Tritium::Pattern>::shared_ptr pPattern = pPatternList->get( nSelectedPattern ); T<Tritium::Pattern>::shared_ptr pNewPattern = pPattern->copy(); pPatternList->add( pNewPattern ); // rename the copied pattern PatternPropertiesDialog *dialog = new PatternPropertiesDialog( this, pNewPattern, true ); if ( dialog->exec() == QDialog::Accepted ) { pSong->set_modified( true ); pEngine->setSelectedPatternNumber(pPatternList->get_size() - 1); // select the last pattern (the copied one) if (pSong->get_mode() == Song::PATTERN_MODE) { pEngine->sequencer_setNextPattern( pPatternList->get_size() - 1, false, false ); // select the last pattern (the new copied pattern) } } else { pPatternList->del( pNewPattern ); pNewPattern.reset(); } delete dialog; CompositeApp::get_instance()->getSongEditorPanel()->updateAll(); }
void SongEditorPatternList::patternPopup_load() { Engine *engine = g_engine; int tmpselectedpatternpos = engine->getSelectedPatternNumber(); T<Song>::shared_ptr song = engine->getSong(); PatternList *pPatternList = song->get_pattern_list(); T<Instrument>::shared_ptr instr = engine->get_sampler()->get_instrument_list()->get( 0 ); assert( instr ); QDir dirPattern( g_engine->get_preferences()->getDataDirectory() + "/patterns" ); std::auto_ptr<QFileDialog> fd( new QFileDialog ); fd->setFileMode(QFileDialog::ExistingFile); fd->setFilter( trUtf8("Hydrogen Pattern (*.h2pattern)") ); fd->setDirectory(dirPattern ); fd->setWindowTitle( trUtf8( "Open Pattern" ) ); QString filename; if (fd->exec() == QDialog::Accepted) { filename = fd->selectedFiles().first(); } else { return; } LocalFileMng mng(g_engine); LocalFileMng fileMng(g_engine); T<Pattern>::shared_ptr err = fileMng.loadPattern( filename ); if ( err == 0 ) { ERRORLOG( "Error loading the pattern" ); }else{ T<Pattern>::shared_ptr pNewPattern = err; pPatternList->add( pNewPattern ); song->set_modified( true ); createBackground(); update(); } int listsize = pPatternList->get_size(); engine->setSelectedPatternNumber( listsize -1 ); T<Pattern>::shared_ptr pTemp = pPatternList->get( engine->getSelectedPatternNumber() ); pPatternList->replace( pPatternList->get( tmpselectedpatternpos ), listsize -1); pPatternList->replace( pTemp, tmpselectedpatternpos ); listsize = pPatternList->get_size(); engine->setSelectedPatternNumber( listsize -1 ); patternPopup_delete(); engine->setSelectedPatternNumber( tmpselectedpatternpos ); CompositeApp::get_instance()->getSongEditorPanel()->updateAll(); }
void SongEditorPatternList::dropEvent(QDropEvent *event) { QString sText = event->mimeData()->text(); if( sText.startsWith("Songs:") || sText.startsWith("move instrument:") ){ event->acceptProposedAction(); return; } if (sText.startsWith("move pattern:")) { Engine *engine = g_engine; int nSourcePattern = engine->getSelectedPatternNumber(); int nTargetPattern = event->pos().y() / m_nGridHeight; if ( nSourcePattern == nTargetPattern ) { event->acceptProposedAction(); return; } movePatternLine( nSourcePattern , nTargetPattern ); event->acceptProposedAction(); }else { PatternList *pPatternList = g_engine->getSong()->get_pattern_list(); QStringList tokens = sText.split( "::" ); QString sPatternName = tokens.at( 1 ); int nTargetPattern = event->pos().y() / m_nGridHeight; LocalFileMng mng(g_engine); T<Pattern>::shared_ptr err = mng.loadPattern( sPatternName ); if ( err == 0 ) { ERRORLOG( "Error loading the pattern" ); }else{ T<Pattern>::shared_ptr pNewPattern = err; pPatternList->add( pNewPattern ); for (int nPatr = pPatternList->get_size() +1 ; nPatr >= nTargetPattern; nPatr--) { T<Tritium::Pattern>::shared_ptr pPattern = pPatternList->get(nPatr - 1); pPatternList->replace( pPattern, nPatr ); } pPatternList->replace( pNewPattern, nTargetPattern ); g_engine->getSong()->set_modified( true ); createBackground(); update(); } CompositeApp::get_instance()->getSongEditorPanel()->updateAll(); event->acceptProposedAction(); } }
void SongEditor::drawSequence() { QPainter p; p.begin( m_pSequencePixmap ); p.drawPixmap( rect(), *m_pBackgroundPixmap, rect() ); p.end(); T<Song>::shared_ptr song = g_engine->getSong(); PatternList *patList = song->get_pattern_list(); T<Song::pattern_group_t>::shared_ptr pColumns = song->get_pattern_group_vector(); uint listLength = patList->get_size(); for (uint i = 0; i < pColumns->size(); i++) { T<PatternList>::shared_ptr pColumn = (*pColumns)[ i ]; for (uint nPat = 0; nPat < pColumn->get_size(); ++nPat) { T<Tritium::Pattern>::shared_ptr pat = pColumn->get( nPat ); int position = -1; // find the position in pattern list for (uint j = 0; j < listLength; j++) { T<Tritium::Pattern>::shared_ptr pat2 = patList->get( j ); if (pat == pat2) { position = j; break; } } if (position == -1) { DEBUGLOG( QString("[drawSequence] position == -1, group = %1").arg( i ) ); } drawPattern( i, position ); } } // Moving cells p.begin( m_pSequencePixmap ); // p.setRasterOp( Qt::XorROP ); // comix: this composition mode seems to be not available on Mac p.setCompositionMode( QPainter::CompositionMode_Xor ); QPen pen( Qt::gray ); pen.setStyle( Qt::DotLine ); p.setPen( pen ); for ( uint i = 0; i < m_movingCells.size(); i++ ) { int x = 10 + m_nGridWidth * ( m_movingCells[ i ] ).x(); int y = m_nGridHeight * ( m_movingCells[ i ] ).y(); QColor patternColor; patternColor.setRgb( 255, 255, 255 ); p.fillRect( x + 2, y + 4, m_nGridWidth - 3, m_nGridHeight - 7, patternColor ); } }
void SongEditorPatternList::inlineEditPatternName( int row ) { Engine *engine = g_engine; T<Song>::shared_ptr song = engine->getSong(); PatternList *patternList = song->get_pattern_list(); if ( row >= (int)patternList->get_size() ) { return; } patternBeingEdited = patternList->get( row ); line->setGeometry( 23, row * m_nGridHeight , m_nWidth - 23, m_nGridHeight ); line->setText( patternBeingEdited->get_name() ); line->selectAll(); line->show(); line->setFocus(); }
/// Single click, select the next pattern void SongEditorPatternList::mousePressEvent( QMouseEvent *ev ) { int row = (ev->y() / m_nGridHeight); Engine *engine = g_engine; T<Song>::shared_ptr song = engine->getSong(); PatternList *patternList = song->get_pattern_list(); if ( row >= (int)patternList->get_size() ) { return; } if ( (ev->button() == Qt::MidButton) || (ev->modifiers() == Qt::ControlModifier && ev->button() == Qt::RightButton) || (ev->modifiers() == Qt::ControlModifier && ev->button() == Qt::LeftButton) ){ togglePattern( row ); } else { engine->setSelectedPatternNumber( row ); if (ev->button() == Qt::RightButton) { /* if ( song->getMode() == Song::PATTERN_MODE ) { PatternList *pCurrentPatternList = engine->getCurrentPatternList(); if ( pCurrentPatternList->get_size() == 0 ) { // nessun pattern e' attivo. seleziono subito questo. pCurrentPatternList->add( patternList->get( row ) ); } else { engine->setNextPattern( row ); } } */ m_pPatternPopup->popup( QPoint( ev->globalX(), ev->globalY() ) ); } } createBackground(); update(); }
void SongEditor::mouseReleaseEvent( QMouseEvent * /*ev*/ ) { Engine *pEngine = g_engine; PatternList *pPatternList = pEngine->getSong()->get_pattern_list(); T<Song::pattern_group_t>::shared_ptr pColumns = pEngine->getSong()->get_pattern_group_vector(); if ( m_bIsMoving ) { // fine dello spostamento dei pattern g_engine->lock( RIGHT_HERE ); // create the new patterns for ( uint i = 0; i < m_movingCells.size(); i++ ) { QPoint cell = m_movingCells[ i ]; if ( cell.x() < 0 || cell.y() < 0 || cell.y() >= (int)pPatternList->get_size() ) { // skip continue; } // aggiungo un pattern per volta T<PatternList>::shared_ptr pColumn; if ( cell.x() < (int)pColumns->size() ) { pColumn = (*pColumns)[ cell.x() ]; } else { // creo dei patternlist vuoti int nSpaces = cell.x() - pColumns->size(); for ( int i = 0; i <= nSpaces; i++ ) { pColumn.reset( new PatternList() ); pColumns->push_back( pColumn ); } } pColumn->add( pPatternList->get( cell.y() ) ); } if ( m_bIsCtrlPressed ) { // COPY } else { // MOVE // remove the old patterns for ( uint i = 0; i < m_selectedCells.size(); i++ ) { QPoint cell = m_selectedCells[ i ]; T<PatternList>::shared_ptr pColumn; if ( cell.x() < (int)pColumns->size() ) { pColumn = (*pColumns)[ cell.x() ]; } else { pColumn.reset( new PatternList() ); pColumns->push_back( pColumn ); } pColumn->del(pPatternList->get( cell.y() ) ); } } // remove the empty patternlist at the end of the song for ( int i = pColumns->size() - 1; i != 0 ; i-- ) { T<PatternList>::shared_ptr pList = (*pColumns)[ i ]; int nSize = pList->get_size(); if ( nSize == 0 ) { pColumns->erase( pColumns->begin() + i ); pList.reset(); } else { break; } } pEngine->getSong()->set_modified( true ); g_engine->unlock(); m_bIsMoving = false; m_movingCells.clear(); m_selectedCells.clear(); } setCursor( QCursor( Qt::ArrowCursor ) ); m_bShowLasso = false; m_bSequenceChanged = true; m_bIsCtrlPressed = false; update(); }
void SongEditor::mouseMoveEvent(QMouseEvent *ev) { int nRow = ev->y() / m_nGridHeight; int nColumn = ( (int)ev->x() - 10 ) / (int)m_nGridWidth; PatternList *pPatternList = g_engine->getSong()->get_pattern_list(); T<Song::pattern_group_t>::shared_ptr pColumns = g_engine->getSong()->get_pattern_group_vector(); if ( m_bIsMoving ) { // WARNINGLOG( "[mouseMoveEvent] Move patterns not implemented yet" ); int nRowDiff = nRow - m_clickPoint.y(); int nColumnDiff = nColumn - m_clickPoint.x(); // DEBUGLOG( "[mouseMoveEvent] row diff: "+ to_string( nRowDiff ) ); // DEBUGLOG( "[mouseMoveEvent] col diff: "+ to_string( nColumnDiff ) ); for ( int i = 0; i < (int)m_movingCells.size(); i++ ) { QPoint cell = m_movingCells[ i ]; m_movingCells[ i ].setX( m_selectedCells[ i ].x() + nColumnDiff ); m_movingCells[ i ].setY( m_selectedCells[ i ].y() + nRowDiff ); } m_bSequenceChanged = true; update(); return; } if ( m_bShowLasso ) { // SELECTION setCursor( QCursor( Qt::CrossCursor ) ); int x = ev->x(); int y = ev->y(); if ( x < 0 ) { x = 0; } if ( y < 0 ) { y = 0; } m_lasso.setBottomRight( QPoint( x, y ) ); // aggiorno la lista di celle selezionate m_selectedCells.clear(); int nStartColumn = (int)( ( m_lasso.left() - 10.0 ) / m_nGridWidth ); int nEndColumn = nColumn; if ( nStartColumn > nEndColumn ) { int nTemp = nEndColumn; nEndColumn = nStartColumn; nStartColumn = nTemp; } int nStartRow = m_lasso.top() / m_nGridHeight; int nEndRow = nRow; if ( nStartRow > nEndRow ) { int nTemp = nEndRow; nEndRow = nStartRow; nStartRow = nTemp; } for ( int nRow = nStartRow; nRow <= nEndRow; nRow++ ) { for ( int nCol = nStartColumn; nCol <= nEndColumn; nCol++ ) { if ( nRow >= (int)pPatternList->get_size() || nRow < 0 || nCol < 0 ) { return; } T<Tritium::Pattern>::shared_ptr pPattern = pPatternList->get( nRow ); if ( nCol < (int)pColumns->size() ) { T<PatternList>::shared_ptr pColumn = ( *pColumns )[ nCol ]; for ( uint i = 0; i < pColumn->get_size(); i++) { if ( pColumn->get(i) == pPattern ) { // esiste un pattern in questa posizione m_selectedCells.push_back( QPoint( nCol, nRow ) ); } } } } } m_bSequenceChanged = true; update(); } }
void SongEditor::mousePressEvent( QMouseEvent *ev ) { if ( ev->x() < 10 ) { return; } int nRow = ev->y() / m_nGridHeight; int nColumn = ( (int)ev->x() - 10 ) / (int)m_nGridWidth; if ( ev->modifiers() == Qt::ControlModifier ) { DEBUGLOG( "[mousePressEvent] CTRL pressed!" ); m_bIsCtrlPressed = true; } else { m_bIsCtrlPressed = false; } Engine *pEngine = g_engine; T<Song>::shared_ptr pSong = pEngine->getSong(); PatternList *pPatternList = pSong->get_pattern_list(); // don't lock the audio driver before checking that... if ( nRow >= (int)pPatternList->get_size() || nRow < 0 || nColumn < 0 ) { return; } g_engine->lock( RIGHT_HERE ); SongEditorActionMode actionMode = CompositeApp::get_instance()->getSongEditorPanel()->getActionMode(); if ( actionMode == SELECT_ACTION ) { bool bOverExistingPattern = false; for ( uint i = 0; i < m_selectedCells.size(); i++ ) { QPoint cell = m_selectedCells[ i ]; if ( cell.x() == nColumn && cell.y() == nRow ) { bOverExistingPattern = true; break; } } if ( bOverExistingPattern ) { // MOVE PATTERNS // DEBUGLOG( "[mousePressEvent] Move patterns" ); m_bIsMoving = true; m_bShowLasso = false; m_movingCells = m_selectedCells; m_clickPoint.setX( nColumn ); m_clickPoint.setY( nRow ); } else { // DEBUGLOG( "[mousePressEvent] Select patterns" ); // select patterns m_bShowLasso = true; m_lasso.setCoords( ev->x(), ev->y(), ev->x(), ev->y() ); setCursor( QCursor( Qt::CrossCursor ) ); m_selectedCells.clear(); m_selectedCells.push_back( QPoint( nColumn, nRow ) ); } } else if ( actionMode == DRAW_ACTION ) { T<Tritium::Pattern>::shared_ptr pPattern = pPatternList->get( nRow ); T<Song::pattern_group_t>::shared_ptr pColumns = pSong->get_pattern_group_vector(); // E' la lista di "colonne" di pattern if ( nColumn < (int)pColumns->size() ) { T<PatternList>::shared_ptr pColumn = ( *pColumns )[ nColumn ]; bool bFound = false; unsigned nColumnIndex = 0; for ( nColumnIndex = 0; nColumnIndex < pColumn->get_size(); nColumnIndex++) { if ( pColumn->get( nColumnIndex ) == pPattern ) { // il pattern e' gia presente bFound = true; break; } } if ( bFound ) { // DELETE PATTERN // DEBUGLOG( "[mousePressEvent] delete pattern" ); pColumn->del( nColumnIndex ); // elimino le colonne vuote for ( int i = pColumns->size() - 1; i >= 0; i-- ) { T<PatternList>::shared_ptr pColumn = ( *pColumns )[ i ]; if ( pColumn->get_size() == 0 ) { pColumns->erase( pColumns->begin() + i ); pColumn.reset(); } else { break; } } } else { if ( nColumn < (int)pColumns->size() ) { // ADD PATTERN // DEBUGLOG( "[mousePressEvent] add pattern" ); m_selectedCells.clear(); pColumn->add( pPattern ); } } } else { // ADD PATTERN (with spaces..) m_selectedCells.clear(); int nSpaces = nColumn - pColumns->size(); // DEBUGLOG( "[mousePressEvent] add pattern (with " + to_string( nSpaces ) + " spaces)" ); T<PatternList>::shared_ptr pColumn( new PatternList() ); pColumns->push_back( pColumn ); for ( int i = 0; i < nSpaces; i++ ) { pColumn.reset( new PatternList() ); pColumns->push_back( pColumn ); } pColumn->add( pPattern ); } pSong->set_modified( true ); } g_engine->unlock(); // update m_bSequenceChanged = true; update(); }
void SongEditorPatternList::patternPopup_delete() { Engine *pEngine = g_engine; // int state = engine->get_transport()->get_state(); // // per ora non lascio possibile la cancellazione del pattern durante l'esecuzione // // da togliere quando correggo il bug // if (state == PLAYING) { // QMessageBox::information( this, "Composite", trUtf8("Can't delete the pattern while the audio engine is playing")); // return; // } if ( pEngine->getSong()->get_mode() == Song::PATTERN_MODE ) { pEngine->sequencer_setNextPattern( -1, false, false ); // reimposto il prossimo pattern a NULL, altrimenti viene scelto quello che sto distruggendo ora... } // pEngine->sequencer_stop(); // "lock engine" I am not sure, but think this is unnecessarily. -wolke- // g_engine->lock( RIGHT_HERE ); T<Song>::shared_ptr song = pEngine->getSong(); PatternList *pSongPatternList = song->get_pattern_list(); T<Pattern>::shared_ptr pattern = pSongPatternList->get( pEngine->getSelectedPatternNumber() ); DEBUGLOG( QString("[patternPopup_delete] Delete pattern: %1 @%2").arg(pattern->get_name()).arg( (long)pattern.get() ) ); pSongPatternList->del(pattern); T<Song::pattern_group_t>::shared_ptr patternGroupVect = song->get_pattern_group_vector(); uint i = 0; while (i < patternGroupVect->size() ) { T<PatternList>::shared_ptr list = (*patternGroupVect)[i]; uint j = 0; while ( j < list->get_size() ) { T<Tritium::Pattern>::shared_ptr pOldPattern = list->get( j ); if (pOldPattern == pattern ) { list->del( j ); continue; } j++; } // for (uint j = 0; j < list->get_size(); j++) { // Pattern *pOldPattern = list->get( j ); // if (pOldPattern == pattern ) { // list->del( j ); // } // } /* if (list->get_size() == 0 ) { patternGroupVect->erase( patternGroupVect->begin() + i ); delete list; list = NULL; } else { */ i++; // } } T<PatternList>::shared_ptr list = pEngine->getCurrentPatternList(); list->del( pattern ); // se esiste, seleziono il primo pattern if ( pSongPatternList->get_size() > 0 ) { T<Tritium::Pattern>::shared_ptr pFirstPattern = pSongPatternList->get( 0 ); list->add( pFirstPattern ); // Cambio due volte...cosi' il pattern editor viene costretto ad aggiornarsi pEngine->setSelectedPatternNumber( -1 ); pEngine->setSelectedPatternNumber( 0 ); } else { // there's no patterns.. T<Pattern>::shared_ptr emptyPattern = Pattern::get_empty_pattern(); emptyPattern->set_name( trUtf8("Pattern 1") ); emptyPattern->set_category( trUtf8("not_categorized") ); pSongPatternList->add( emptyPattern ); pEngine->setSelectedPatternNumber( -1 ); pEngine->setSelectedPatternNumber( 0 ); } pattern.reset(); song->set_modified( true ); // "unlock" I am not sure, but think this is unnecessarily. -wolke- // g_engine->unlock(); ( CompositeApp::get_instance() )->getSongEditorPanel()->updateAll(); }