summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2011-06-06 16:49:02 +0000
committerFlorian Jung <flo@windfisch.org>2011-06-06 16:49:02 +0000
commit6c8a1eb61743e3fa83925d40c14d3a6754c8359f (patch)
tree0c0645ce9f04badea5a17aa6651c17e0cb65b34a
parent441642e7da807d506b794e5a62b7c2426bd7b95f (diff)
implemented functions for shrinking, expanding and cleaning parts
-rw-r--r--muse2/muse/app.cpp47
-rw-r--r--muse2/muse/app.h3
-rw-r--r--muse2/muse/functions.cpp104
-rw-r--r--muse2/muse/functions.h5
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp2
5 files changed, 133 insertions, 28 deletions
diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp
index 9e2f6c9a..6b9f2b5b 100644
--- a/muse2/muse/app.cpp
+++ b/muse2/muse/app.cpp
@@ -54,6 +54,7 @@
#include "tools.h"
#include "visibletracks.h"
#include "widgets/unusedwavefiles.h"
+#include "functions.h"
#ifdef DSSI_SUPPORT
#include "dssihost.h"
@@ -977,6 +978,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
editPaste2TrackAction = new QAction(QIcon(*editpaste2TrackIconSet), tr("Paste to &track"), this);
editPasteC2TAction = new QAction(QIcon(*editpasteClone2TrackIconSet), tr("Paste clone to trac&k"), this);
editDeleteSelectedAction = new QAction(QIcon(*edit_track_delIcon), tr("Delete Selected Tracks"), this);
+
+ editShrinkPartsAction = new QAction(tr("Shrink selected parts"), this); //FINDMICH TODO tooltips!
+ editExpandPartsAction = new QAction(tr("Expand selected parts"), this);
+ editCleanPartsAction = new QAction(tr("Clean selected parts"), this);
addTrack = new QMenu(tr("Add Track"), this);
@@ -1127,6 +1132,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
connect(editPasteC2TAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editDeleteSelectedAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
+ connect(editShrinkPartsAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
+ connect(editExpandPartsAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
+ connect(editCleanPartsAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
+
connect(editSelectAllAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editDeselectAllAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
connect(editInvertSelectionAction, SIGNAL(triggered()), editSignalMapper, SLOT(map()));
@@ -1143,6 +1152,9 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
editSignalMapper->setMapping(editPasteC2TAction, CMD_PASTE_CLONE_TO_TRACK);
editSignalMapper->setMapping(editInsertEMAction, CMD_INSERTMEAS);
editSignalMapper->setMapping(editDeleteSelectedAction, CMD_DELETE_TRACK);
+ editSignalMapper->setMapping(editShrinkPartsAction, CMD_SHRINK_PART);
+ editSignalMapper->setMapping(editExpandPartsAction, CMD_EXPAND_PART);
+ editSignalMapper->setMapping(editCleanPartsAction, CMD_CLEAN_PART);
editSignalMapper->setMapping(editSelectAllAction, CMD_SELECT_ALL);
editSignalMapper->setMapping(editDeselectAllAction, CMD_SELECT_NONE);
editSignalMapper->setMapping(editInvertSelectionAction, CMD_SELECT_INVERT);
@@ -1361,6 +1373,10 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
menuEdit->addAction(editPaste2TrackAction);
menuEdit->addAction(editPasteC2TAction);
menuEdit->addSeparator();
+ menuEdit->addAction(editShrinkPartsAction);
+ menuEdit->addAction(editExpandPartsAction);
+ menuEdit->addAction(editCleanPartsAction);
+ menuEdit->addSeparator();
menuEdit->addAction(editDeleteSelectedAction);
// Moved below. Have to wait until synths are available...
@@ -1389,7 +1405,7 @@ MusE::MusE(int argc, char** argv) : QMainWindow()
menuEdit->addMenu(midiEdit);
-#if 0 // TODO
+#if 0 // TODO FINDMICH delete!
midiEdit->insertItem(tr("Modify Gate Time"), this, SLOT(modifyGateTime()));
midiEdit->insertItem(tr("Modify Velocity"), this, SLOT(modifyVelocity()));
midiEdit->insertItem(tr("Crescendo"), this, SLOT(crescendo()));
@@ -3046,6 +3062,10 @@ void MusE::cmd(int cmd)
song->setFollow(Song::CONTINUOUS);
setFollow();
break;
+
+ case CMD_SHRINK_PART: shrink_parts(); break;
+ case CMD_EXPAND_PART: expand_parts(); break;
+ case CMD_CLEAN_PART: clean_parts(); break;
}
}
@@ -3055,37 +3075,12 @@ void MusE::cmd(int cmd)
void MusE::clipboardChanged()
{
-/*
- //Q3CString subtype("partlist");
- //QString subtype("partlist");
- QMimeSource* ms = QApplication::clipboard()->data(QClipboard::Clipboard);
- if (ms == 0)
- return;
- bool flag = false;
- for (int i = 0; ms->format(i); ++i) {
-// printf("Format <%s\n", ms->format(i));
- if ((strncmp(ms->format(i), "text/midipartlist", 17) == 0)
- || (strncmp(ms->format(i), "text/wavepartlist", 17) == 0)
- // Added by T356. Support mixed .mpt files.
- || (strncmp(ms->format(i), "text/mixedpartlist", 18) == 0)) {
- flag = true;
- break;
- }
- }
-*/
-
bool flag = false;
if(QApplication::clipboard()->mimeData()->hasFormat(QString("text/x-muse-midipartlist")) ||
QApplication::clipboard()->mimeData()->hasFormat(QString("text/x-muse-wavepartlist")) ||
QApplication::clipboard()->mimeData()->hasFormat(QString("text/x-muse-mixedpartlist")))
flag = true;
- //bool flag = false;
- //if(!QApplication::clipboard()->text(QString("x-muse-midipartlist"), QClipboard::Clipboard).isEmpty() ||
- // !QApplication::clipboard()->text(QString("x-muse-wavepartlist"), QClipboard::Clipboard).isEmpty() ||
- // !QApplication::clipboard()->text(QString("x-muse-mixedpartlist"), QClipboard::Clipboard).isEmpty())
- // flag = true;
-
editPasteAction->setEnabled(flag);
editInsertAction->setEnabled(flag);
editPasteCloneAction->setEnabled(flag);
diff --git a/muse2/muse/app.h b/muse2/muse/app.h
index 256154e2..3f539196 100644
--- a/muse2/muse/app.h
+++ b/muse2/muse/app.h
@@ -80,7 +80,7 @@ class MusE : public QMainWindow
CMD_SELECT_ALL, CMD_SELECT_NONE, CMD_SELECT_INVERT,
CMD_SELECT_ILOOP, CMD_SELECT_OLOOP, CMD_SELECT_PARTS,
CMD_FOLLOW_NO, CMD_FOLLOW_JUMP, CMD_FOLLOW_CONTINUOUS ,
- CMD_DELETE_TRACK
+ CMD_DELETE_TRACK, CMD_EXPAND_PART, CMD_SHRINK_PART, CMD_CLEAN_PART
};
//File menu items:
@@ -113,6 +113,7 @@ class MusE : public QMainWindow
QAction *masterGraphicAction, *masterListAction;
QAction *midiTransformerAction;
QAction *editSongInfoAction;
+ QAction *editCleanPartsAction, *editShrinkPartsAction, *editExpandPartsAction;
public:
QAction *startScoreEditAction, *startPianoEditAction, *startDrumEditAction, *startListEditAction, *startWaveEditAction;
QMenu *scoreSubmenu, *scoreOneStaffPerTrackSubsubmenu, *scoreAllInOneSubsubmenu;
diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp
index a6c9c95a..3d10a878 100644
--- a/muse2/muse/functions.cpp
+++ b/muse2/muse/functions.cpp
@@ -749,7 +749,7 @@ void paste_at(Part* dest_part, const QString& pt, int pos)
Part* newPart = dest_part->clone();
newPart->setLenTick(newPart->lenTick()+diff);
// Indicate no undo, and do port controller values but not clone parts.
- operations.push_back(UndoOp(UndoOp::ModifyPart,dest_part, newPart, true, false)); //FINDMICHJETZT oder andersrum?
+ operations.push_back(UndoOp(UndoOp::ModifyPart,dest_part, newPart, true, false));
dest_part = newPart; // reassign TODO FINDME does this work, or has dest_part to be a nonconst reference?
}
// Indicate no undo, and do not do port controller values and clone parts.
@@ -831,6 +831,108 @@ void select_not_in_loop(const std::set<Part*>& parts)
}
+void shrink_parts()
+{
+ Undo operations;
+
+ TrackList* tracks = song->tracks();
+ for (iTrack track = tracks->begin(); track != tracks->end(); track++)
+ for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++)
+ if (part->second->selected())
+ {
+ EventList* events=part->second->events();
+ unsigned len=0;
+
+ for (iEvent ev=events->begin(); ev!=events->end(); ev++)
+ if (ev->second.endTick() > len)
+ len=ev->second.endTick();
+
+ if (len > part->second->lenTick())
+ len = part->second->lenTick();
+
+ if (len != part->second->lenTick())
+ {
+ MidiPart* new_part = new MidiPart(*(MidiPart*)part->second);
+ new_part->setLenTick(len);
+ operations.push_back(UndoOp(UndoOp::ModifyPart, part->second, new_part, true, false));
+ }
+ }
+
+ song->applyOperationGroup(operations);
+}
+
+void expand_parts()
+{
+ Undo operations;
+
+ TrackList* tracks = song->tracks();
+ for (iTrack track = tracks->begin(); track != tracks->end(); track++)
+ for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++)
+ if (part->second->selected())
+ {
+ EventList* events=part->second->events();
+ unsigned len=part->second->lenTick();
+
+ for (iEvent ev=events->begin(); ev!=events->end(); ev++)
+ if (ev->second.endTick() > len)
+ len=ev->second.endTick();
+
+ if (len != part->second->lenTick())
+ {
+ MidiPart* new_part = new MidiPart(*(MidiPart*)part->second);
+ new_part->setLenTick(len);
+ operations.push_back(UndoOp(UndoOp::ModifyPart, part->second, new_part, true, false));
+ }
+ }
+
+ song->applyOperationGroup(operations);
+}
+
+void clean_parts()
+{
+ Undo operations;
+ set<Part*> already_processed;
+
+ TrackList* tracks = song->tracks();
+ for (iTrack track = tracks->begin(); track != tracks->end(); track++)
+ for (iPart part = (*track)->parts()->begin(); part != (*track)->parts()->end(); part++)
+ if ((part->second->selected()) && (already_processed.find(part->second)==already_processed.end()))
+ {
+ // find out the length of the longest clone of this part;
+ // avoid processing eventlist multiple times (because of
+ // multiple clones)
+ unsigned len=0;
+
+ Part* part_it=part->second;
+ do
+ {
+ if (part_it->lenTick() > len)
+ len=part_it->lenTick();
+
+ already_processed.insert(part_it);
+ part_it=part_it->nextClone();
+ } while ((part_it!=part->second) && (part_it!=NULL));
+
+
+ // erase all events exceeding the longest clone of this part
+ // (i.e., erase all hidden events) or shorten them
+ EventList* el = part->second->events();
+ for (iEvent ev=el->begin(); ev!=el->end(); ev++)
+ if (ev->second.tick() >= len)
+ operations.push_back(UndoOp(UndoOp::DeleteEvent, ev->second, part->second, true, true));
+ else if (ev->second.endTick() > len)
+ {
+ Event new_event = ev->second.clone();
+ new_event.setLenTick(len - ev->second.tick());
+
+ operations.push_back(UndoOp(UndoOp::ModifyEvent, new_event, ev->second, part->second, true, true));
+ }
+ }
+
+ song->applyOperationGroup(operations);
+}
+
+
void read_function_dialog_config(Xml& xml)
{
if (erase_dialog==NULL)
diff --git a/muse2/muse/functions.h b/muse2/muse/functions.h
index bc2bb8f4..8a1eb3ed 100644
--- a/muse2/muse/functions.h
+++ b/muse2/muse/functions.h
@@ -84,6 +84,11 @@ void select_invert(const std::set<Part*>& parts);
void select_in_loop(const std::set<Part*>& parts);
void select_not_in_loop(const std::set<Part*>& parts);
+//functions for parts
+void shrink_parts();
+void expand_parts();
+void clean_parts();
+
//functions for reading and writing default values
class Xml;
void read_function_dialog_config(Xml& xml);
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index f1c305d6..450d6f98 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -4452,6 +4452,8 @@ void staff_t::update_part_indices()
/* BUGS and potential bugs
+ * o clones aren't marked as clones any more :(
+ *
* o when the keymap is not used, this will probably lead to a bug
* o tied notes don't work properly when there's a key-change in
* between, for example, when a cis is tied to a des