summaryrefslogtreecommitdiff
path: root/muse2
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2011-09-13 16:02:25 +0000
committerFlorian Jung <flo@windfisch.org>2011-09-13 16:02:25 +0000
commitebf207e2c5e457e9a6fa93dfdd31b96ea379de9a (patch)
treebbcbfb67f0719e456421cc1aeb056ebf04f5e53d /muse2
parentfb0fbe8f65cca18487567fd1e2db63c99c024bd8 (diff)
paste in midi editors now respects raster and amount and provides a sane
default for amount
Diffstat (limited to 'muse2')
-rw-r--r--muse2/muse/functions.cpp144
-rw-r--r--muse2/muse/functions.h4
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp4
3 files changed, 110 insertions, 42 deletions
diff --git a/muse2/muse/functions.cpp b/muse2/muse/functions.cpp
index d6cfa7d0..8e9a7cd5 100644
--- a/muse2/muse/functions.cpp
+++ b/muse2/muse/functions.cpp
@@ -62,6 +62,15 @@ using namespace std;
using MusEConfig::config;
+
+// unit private functions:
+
+bool read_eventlist_and_part(Xml& xml, EventList* el, int* part_id);
+
+// -----------------------
+
+
+
set<Part*> partlist_to_set(PartList* pl)
{
set<Part*> result;
@@ -866,25 +875,76 @@ void copy_notes(const set<Part*>& parts, int range)
QApplication::clipboard()->setMimeData(drag, QClipboard::Clipboard);
}
+unsigned get_groupedevents_len(const QString& pt)
+{
+ unsigned maxlen=0;
+
+ Xml xml(pt.toLatin1().constData());
+ for (;;)
+ {
+ Xml::Token token = xml.parse();
+ const QString& tag = xml.s1();
+ switch (token)
+ {
+ case Xml::Error:
+ case Xml::End:
+ return maxlen;
+
+ case Xml::TagStart:
+ if (tag == "eventlist")
+ {
+ EventList el;
+ int part_id;
+ if (read_eventlist_and_part(xml, &el, &part_id))
+ {
+ unsigned len = el.rbegin()->first;
+ if (len > maxlen) maxlen=len;
+ }
+ }
+ else
+ xml.unknown("get_clipboard_len");
+ break;
+
+ case Xml::Attribut:
+ case Xml::TagEnd:
+ default:
+ break;
+ }
+ }
+
+ return maxlen; // see also the return statement above!
+}
+
+unsigned get_clipboard_len()
+{
+ QString tmp="x-muse-groupedeventlists"; // QClipboard::text() expects a QString&, not a QString :(
+ QString s = QApplication::clipboard()->text(tmp, QClipboard::Clipboard); // TODO CHECK Tim.
+
+ return get_groupedevents_len(s);
+}
+
bool paste_notes(Part* paste_into_part)
{
- // TODO FINDMICHJETZT sane defaults for raster!
+ unsigned temp_begin = AL::sigmap.raster1(song->cpos(),0);
+ unsigned temp_end = AL::sigmap.raster2(temp_begin + get_clipboard_len(), 0);
+ paste_events_dialog->raster = temp_end - temp_begin;
paste_events_dialog->into_single_part_allowed = (paste_into_part!=NULL);
if (!paste_events_dialog->exec())
return false;
paste_notes(paste_events_dialog->max_distance, paste_events_dialog->always_new_part,
- paste_events_dialog->never_new_part, paste_events_dialog->into_single_part ? paste_into_part : NULL);
+ paste_events_dialog->never_new_part, paste_events_dialog->into_single_part ? paste_into_part : NULL,
+ paste_events_dialog->number, paste_events_dialog->raster);
return true;
}
-void paste_notes(int max_distance, bool always_new_part, bool never_new_part, Part* paste_into_part)
+void paste_notes(int max_distance, bool always_new_part, bool never_new_part, Part* paste_into_part, int amount, int raster)
{
QString tmp="x-muse-groupedeventlists"; // QClipboard::text() expects a QString&, not a QString :(
QString s = QApplication::clipboard()->text(tmp, QClipboard::Clipboard); // TODO CHECK Tim.
- paste_at(s, song->cpos(), max_distance, always_new_part, never_new_part, paste_into_part);
+ paste_at(s, song->cpos(), max_distance, always_new_part, never_new_part, paste_into_part, amount, raster);
}
@@ -996,7 +1056,7 @@ bool read_eventlist_and_part(Xml& xml, EventList* el, int* part_id) // true on s
}
}
-void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part, bool never_new_part, Part* paste_into_part)
+void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part, bool never_new_part, Part* paste_into_part, int amount, int raster)
{
Undo operations;
map<Part*, unsigned> expand_map;
@@ -1023,6 +1083,7 @@ void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part
{
Part* dest_part;
Track* dest_track;
+ Part* old_dest_part;
if (paste_into_part == NULL)
dest_part = MusEUtil::partFromSerialNumber(part_id);
@@ -1036,52 +1097,59 @@ void paste_at(const QString& pt, int pos, int max_distance, bool always_new_part
else
{
dest_track=dest_part->track();
-
+ old_dest_part=dest_part;
unsigned first_paste_tick = el.begin()->first + pos;
- if ( (dest_part->tick() > first_paste_tick) || // dest_part begins too late
+ bool create_new_part = ( (dest_part->tick() > first_paste_tick) || // dest_part begins too late
( ( (dest_part->endTick() + max_distance < first_paste_tick) || // dest_part is too far away
- always_new_part ) && !never_new_part ) )
- {
- Part* old_dest_part=dest_part;
- dest_part = dest_track->newPart();
- dest_part->events()->incARef(-1); // the later song->applyOperationGroup() will increment it
- // so we must decrement it first :/
- dest_part->setTick(AL::sigmap.raster1(first_paste_tick, config.division));
-
- new_part_map[old_dest_part].insert(dest_part);
- operations.push_back(UndoOp(UndoOp::AddPart, dest_part));
- }
+ always_new_part ) && !never_new_part ) ); // respect function arguments
- for (iEvent i = el.begin(); i != el.end(); ++i)
+ for (int i=0;i<amount;i++)
{
- Event e = i->second;
- int tick = e.tick() + pos - dest_part->tick();
- if (tick<0)
+ unsigned curr_pos = pos + i*raster;
+ first_paste_tick = el.begin()->first + curr_pos;
+
+ if (create_new_part)
{
- printf("ERROR: trying to add event before current part! ignoring this event\n");
- continue;
- }
+ dest_part = dest_track->newPart();
+ dest_part->events()->incARef(-1); // the later song->applyOperationGroup() will increment it
+ // so we must decrement it first :/
+ dest_part->setTick(AL::sigmap.raster1(first_paste_tick, config.division));
- e.setTick(tick);
- e.setSelected(true);
+ new_part_map[old_dest_part].insert(dest_part);
+ operations.push_back(UndoOp(UndoOp::AddPart, dest_part));
+ }
- if (e.endTick() > dest_part->lenTick()) // event exceeds part?
+ for (iEvent i = el.begin(); i != el.end(); ++i)
{
- if (dest_part->hasHiddenEvents()) // auto-expanding is forbidden?
+ Event e = i->second.clone();
+ int tick = e.tick() + curr_pos - dest_part->tick();
+ if (tick<0)
{
- if (e.tick() < dest_part->lenTick())
- e.setLenTick(dest_part->lenTick() - e.tick()); // clip
- else
- e.setLenTick(0); // don't insert that note at all
+ printf("ERROR: trying to add event before current part! ignoring this event\n");
+ continue;
}
- else
+
+ e.setTick(tick);
+ e.setSelected(true);
+
+ if (e.endTick() > dest_part->lenTick()) // event exceeds part?
{
- if (e.endTick() > expand_map[dest_part])
- expand_map[dest_part]=e.endTick();
+ if (dest_part->hasHiddenEvents()) // auto-expanding is forbidden?
+ {
+ if (e.tick() < dest_part->lenTick())
+ e.setLenTick(dest_part->lenTick() - e.tick()); // clip
+ else
+ e.setLenTick(0); // don't insert that note at all
+ }
+ else
+ {
+ if (e.endTick() > expand_map[dest_part])
+ expand_map[dest_part]=e.endTick();
+ }
}
+
+ if (e.lenTick() != 0) operations.push_back(UndoOp(UndoOp::AddEvent,e, dest_part, false, false));
}
-
- if (e.lenTick() != 0) operations.push_back(UndoOp(UndoOp::AddEvent,e, dest_part, false, false));
}
}
}
diff --git a/muse2/muse/functions.h b/muse2/muse/functions.h
index 98376896..77777f04 100644
--- a/muse2/muse/functions.h
+++ b/muse2/muse/functions.h
@@ -85,9 +85,9 @@ bool legato();
//functions for copy'n'paste
void copy_notes(const std::set<Part*>& parts, int range);
bool paste_notes(Part* paste_into_part=NULL); // shows a dialog
-void paste_notes(int max_distance=3072, bool always_new_part=false, bool never_new_part=false, Part* paste_into_part=NULL);
+void paste_notes(int max_distance=3072, bool always_new_part=false, bool never_new_part=false, Part* paste_into_part=NULL, int amount=1, int raster=3072);
QMimeData* selected_events_to_mime(const std::set<Part*>& parts, int range);
-void paste_at(const QString& pt, int pos, int max_distance=3072, bool always_new_part=false, bool never_new_part=false, Part* paste_into_part=NULL);
+void paste_at(const QString& pt, int pos, int max_distance=3072, bool always_new_part=false, bool never_new_part=false, Part* paste_into_part=NULL, int amount=1, int raster=3072);
//functions for selections
void select_all(const std::set<Part*>& parts);
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index d49658ae..11632ef3 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -4534,8 +4534,8 @@ void ScoreCanvas::add_new_parts(const std::map< Part*, std::set<Part*> >& param)
* o pasting in editors sometimes fails oO? ( ERROR: reading eventlist from clipboard failed. ignoring this one... )
* o ctrl+shift+c for editors
* o TEST pasting in editors!
- * o sane default for raster
- * o use raster and amount in paste_notes!
+ * x sane default for raster
+ * x use raster and amount in paste_notes!
* x clone-bug
* x pasting in editors: add dialogs
* x when pasting and creating new parts, inform the editors about that!