diff options
-rw-r--r-- | muse2/ChangeLog | 2 | ||||
-rw-r--r-- | muse2/muse/arranger/pcanvas.cpp | 10 | ||||
-rw-r--r-- | muse2/muse/functions.cpp | 77 | ||||
-rw-r--r-- | muse2/muse/functions.h | 2 | ||||
-rw-r--r-- | muse2/muse/midiedit/scoreedit.cpp | 3 |
5 files changed, 92 insertions, 2 deletions
diff --git a/muse2/ChangeLog b/muse2/ChangeLog index 7a1d8d9b..4e59198b 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,3 +1,5 @@ +21.11.2011: + - added super-glue feature (flo) 07.11.2011: - fixed restore-window-state bug (flo) - fixed dialog translation problem (flo) diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index 366766ae..d19fa082 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -54,6 +54,7 @@ #include "shortcuts.h" #include "gconfig.h" #include "app.h" +#include "functions.h" #include "filedialog.h" #include "marker/marker.h" #include "mpevent.h" @@ -664,6 +665,8 @@ QMenu* PartCanvas::genItemPopup(CItem* item) act_split->setData(2); QAction *act_glue = partPopup->addAction(QIcon(*glueIcon), tr("glue")); act_glue->setData(3); + QAction *act_superglue = partPopup->addAction(QIcon(*glueIcon), tr("super glue (merge selection)")); + act_superglue->setData(6); QAction *act_declone = partPopup->addAction(tr("de-clone")); act_declone->setData(15); @@ -752,6 +755,9 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt) case 5: copy(pl); break; + case 6: + MusECore::merge_selected_parts(); + break; case 14: // wave edit emit startEditor(pl, 4); @@ -772,7 +778,7 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt) // Indicate undo, and do port controller values but not clone parts. // changed by flo93: removed start and endUndo, instead changed first bool to true MusEGlobal::audio->msgChangePart(spart, dpart, true, true, false); - break; // Has to be break here, right? + break; } case 16: // Export to file { @@ -800,7 +806,7 @@ void PartCanvas::itemPopup(CItem* item, int n, const QPoint& pt) for (MusECore::iEvent e = el->begin(); e != el->end(); ++e) { MusECore::Event event = e->second; - MusECore::SndFileR f = event.sndFile(); + MusECore::SndFileR f = event.sndFile(); if (f.isNull()) continue; str.append(QString("\n@") + QString().setNum(event.tick()) + QString(" len:") + diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp index 7459f30b..77825f52 100644 --- a/muse2/muse/functions.cpp +++ b/muse2/muse/functions.cpp @@ -1383,4 +1383,81 @@ void clean_parts() MusEGlobal::song->applyOperationGroup(operations); } +bool merge_selected_parts() +{ + set<Part*> temp = get_all_selected_parts(); + return merge_parts(temp); +} + +bool merge_parts(const set<Part*>& parts) +{ + set<Track*> tracks; + for (set<Part*>::iterator it=parts.begin(); it!=parts.end(); it++) + tracks.insert( (*it)->track() ); + + Undo operations; + + // process tracks separately + for (set<Track*>::iterator t_it=tracks.begin(); t_it!=tracks.end(); t_it++) + { + Track* track=*t_it; + + unsigned begin=MAXINT, end=0; + Part* first_part=NULL; + + // find begin of the first and end of the last part + for (set<Part*>::iterator it=parts.begin(); it!=parts.end(); it++) + if ((*it)->track()==track) + { + Part* p=*it; + if (p->tick() < begin) + { + begin=p->tick(); + first_part=p; + } + + if (p->endTick() > end) + end=p->endTick(); + } + + if (begin==MAXINT || end==0) + { + printf("THIS SHOULD NEVER HAPPEN: begin==MAXINT || end==0 in merge_parts()\n"); + continue; // skip the actual work, as we cannot work under errornous conditions. + } + + // create and prepare the new part + Part* new_part = track->newPart(first_part); + new_part->setTick(begin); + new_part->setLenTick(end-begin); + + EventList* new_el = new_part->events(); + new_el->incARef(-1); // the later MusEGlobal::song->applyOperationGroup() will increment it + // so we must decrement it first :/ + new_el->clear(); + + // copy all events from the source parts into the new part + for (set<Part*>::iterator p_it=parts.begin(); p_it!=parts.end(); p_it++) + if ((*p_it)->track()==track) + { + EventList* old_el= (*p_it)->events(); + for (iEvent ev_it=old_el->begin(); ev_it!=old_el->end(); ev_it++) + { + Event new_event=ev_it->second; + new_event.setTick( new_event.tick() + (*p_it)->tick() - new_part->tick() ); + new_el->add(new_event); + } + } + + // delete all the source parts + for (set<Part*>::iterator it=parts.begin(); it!=parts.end(); it++) + if ((*it)->track()==track) + operations.push_back( UndoOp(UndoOp::DeletePart, *it) ); + // and add the new one + operations.push_back( UndoOp(UndoOp::AddPart, new_part) ); + } + + return MusEGlobal::song->applyOperationGroup(operations); +} + } // namespace MusECore diff --git a/muse2/muse/functions.h b/muse2/muse/functions.h index 2cf9c245..c81dd2bc 100644 --- a/muse2/muse/functions.h +++ b/muse2/muse/functions.h @@ -102,6 +102,8 @@ void shrink_parts(int raster=-1); //negative values mean "config.division" void expand_parts(int raster=-1); void schedule_resize_all_same_len_clone_parts(Part* part, unsigned new_len, Undo& operations); void clean_parts(); +bool merge_selected_parts(); +bool merge_parts(const std::set<Part*>& parts); } // namespace MusECore diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp index e313c417..b06f2487 100644 --- a/muse2/muse/midiedit/scoreedit.cpp +++ b/muse2/muse/midiedit/scoreedit.cpp @@ -4595,6 +4595,9 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set<MusECo * ? pasting in editors sometimes fails oO? ( ERROR: reading eventlist * from clipboard failed. ignoring this one... ) [ not reproducible ] * > o non-mdi topwin states aren't restored when launching muse2 somefile.med + * ! o using super glue while a score editor displaying the glued parts + * is open lets muse segfault. this may or may not be fixed in + * the release branch :/ * * CURRENT TODO * > o fix valgrind problems (the two "FINDMICHJETZT" lines in scoreedit.cpp) |