summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse2/ChangeLog2
-rw-r--r--muse2/muse/arranger/pcanvas.cpp10
-rw-r--r--muse2/muse/functions.cpp77
-rw-r--r--muse2/muse/functions.h2
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp3
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)