diff options
author | Florian Jung <flo@windfisch.org> | 2011-09-13 16:02:25 +0000 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2011-09-13 16:02:25 +0000 |
commit | ebf207e2c5e457e9a6fa93dfdd31b96ea379de9a (patch) | |
tree | bbcbfb67f0719e456421cc1aeb056ebf04f5e53d /muse2 | |
parent | fb0fbe8f65cca18487567fd1e2db63c99c024bd8 (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.cpp | 144 | ||||
-rw-r--r-- | muse2/muse/functions.h | 4 | ||||
-rw-r--r-- | muse2/muse/midiedit/scoreedit.cpp | 4 |
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! |