2012-08-09 12:12:43 +02:00
|
|
|
//=============================================================================
|
|
|
|
// MuseScore
|
|
|
|
// Music Composition & Notation
|
|
|
|
//
|
|
|
|
// Copyright (C) 2012 Werner Schweer
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License version 2
|
|
|
|
// as published by the Free Software Foundation and appearing in
|
|
|
|
// the file LICENCE.GPL
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
#include "score.h"
|
|
|
|
#include "utils.h"
|
|
|
|
#include "key.h"
|
|
|
|
#include "clef.h"
|
|
|
|
#include "navigate.h"
|
|
|
|
#include "slur.h"
|
2013-08-22 12:18:14 +02:00
|
|
|
#include "tie.h"
|
2012-08-09 12:12:43 +02:00
|
|
|
#include "note.h"
|
|
|
|
#include "rest.h"
|
|
|
|
#include "chord.h"
|
|
|
|
#include "text.h"
|
|
|
|
#include "sig.h"
|
|
|
|
#include "staff.h"
|
|
|
|
#include "part.h"
|
|
|
|
#include "style.h"
|
|
|
|
#include "page.h"
|
|
|
|
#include "barline.h"
|
|
|
|
#include "tuplet.h"
|
|
|
|
#include "xml.h"
|
|
|
|
#include "ottava.h"
|
|
|
|
#include "trill.h"
|
|
|
|
#include "pedal.h"
|
|
|
|
#include "hairpin.h"
|
|
|
|
#include "textline.h"
|
|
|
|
#include "keysig.h"
|
|
|
|
#include "volta.h"
|
|
|
|
#include "dynamic.h"
|
|
|
|
#include "box.h"
|
|
|
|
#include "harmony.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "stafftext.h"
|
|
|
|
#include "articulation.h"
|
|
|
|
#include "layoutbreak.h"
|
|
|
|
#include "drumset.h"
|
|
|
|
#include "beam.h"
|
|
|
|
#include "lyrics.h"
|
|
|
|
#include "pitchspelling.h"
|
|
|
|
#include "measure.h"
|
|
|
|
#include "tempo.h"
|
|
|
|
#include "sig.h"
|
|
|
|
#include "undo.h"
|
|
|
|
#include "timesig.h"
|
|
|
|
#include "repeat.h"
|
|
|
|
#include "tempotext.h"
|
|
|
|
#include "clef.h"
|
|
|
|
#include "noteevent.h"
|
|
|
|
#include "breath.h"
|
|
|
|
#include "tablature.h"
|
|
|
|
#include "stafftype.h"
|
|
|
|
#include "segment.h"
|
|
|
|
#include "chordlist.h"
|
|
|
|
#include "mscore.h"
|
|
|
|
#include "accidental.h"
|
|
|
|
#include "sequencer.h"
|
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
namespace Ms {
|
|
|
|
|
2012-08-09 12:12:43 +02:00
|
|
|
//---------------------------------------------------------
|
|
|
|
// pasteStaff
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
2013-01-11 18:10:18 +01:00
|
|
|
void Score::pasteStaff(XmlReader& e, ChordRest* dst)
|
2012-08-09 12:12:43 +02:00
|
|
|
{
|
2013-10-14 11:56:54 +02:00
|
|
|
clearSpannerIds();
|
2013-06-19 16:25:29 +02:00
|
|
|
QList<Chord*> graceNotes;
|
2012-08-09 12:12:43 +02:00
|
|
|
int dstStaffStart = dst->staffIdx();
|
|
|
|
int dstTick = dst->tick();
|
2013-06-20 19:01:44 +02:00
|
|
|
bool done = false;
|
2013-01-11 18:10:18 +01:00
|
|
|
while (e.readNextStartElement()) {
|
2013-06-20 19:01:44 +02:00
|
|
|
if (done)
|
|
|
|
break;
|
2013-01-11 18:10:18 +01:00
|
|
|
if (e.name() != "StaffList") {
|
|
|
|
e.unknown();
|
2013-01-17 12:56:14 +01:00
|
|
|
break;
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
2013-08-05 15:27:52 +02:00
|
|
|
QString version = e.attribute("version", "NONE");
|
|
|
|
if(version != MSC_VERSION)
|
|
|
|
break;
|
2013-01-11 18:10:18 +01:00
|
|
|
int tickStart = e.intAttribute("tick", 0);
|
|
|
|
int tickLen = e.intAttribute("len", 0);
|
|
|
|
int srcStaffStart = e.intAttribute("staff", 0);
|
|
|
|
int staves = e.intAttribute("staves", 0);
|
2013-01-21 20:21:41 +01:00
|
|
|
e.setTick(tickStart);
|
2012-08-09 12:12:43 +02:00
|
|
|
|
|
|
|
bool pasted = false;
|
2013-01-11 18:10:18 +01:00
|
|
|
while (e.readNextStartElement()) {
|
2013-06-20 20:13:46 +02:00
|
|
|
if (done)
|
|
|
|
break;
|
2013-01-11 18:10:18 +01:00
|
|
|
if (e.name() != "Staff") {
|
|
|
|
e.unknown();
|
2013-01-17 12:56:14 +01:00
|
|
|
break;
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
2013-01-11 18:10:18 +01:00
|
|
|
int srcStaffIdx = e.attribute("id", "0").toInt();
|
2012-08-09 12:12:43 +02:00
|
|
|
int dstStaffIdx = srcStaffIdx - srcStaffStart + dstStaffStart;
|
2013-06-20 19:01:44 +02:00
|
|
|
if (dstStaffIdx >= nstaves()) {
|
|
|
|
done = true; // break main loop, nothing more to paste
|
2012-08-09 12:12:43 +02:00
|
|
|
break;
|
2013-06-20 19:01:44 +02:00
|
|
|
}
|
2013-07-20 16:14:39 +02:00
|
|
|
|
2013-01-21 20:21:41 +01:00
|
|
|
e.tuplets().clear();
|
2013-07-20 16:14:39 +02:00
|
|
|
bool makeGap = true;
|
2013-01-11 18:10:18 +01:00
|
|
|
while (e.readNextStartElement()) {
|
2012-08-09 12:12:43 +02:00
|
|
|
pasted = true;
|
2013-01-11 18:10:18 +01:00
|
|
|
const QStringRef& tag(e.name());
|
2013-01-07 12:36:06 +01:00
|
|
|
|
2013-06-20 20:13:46 +02:00
|
|
|
if (tag == "tick") {
|
|
|
|
int tick = e.readInt();
|
|
|
|
e.setTick(tick);
|
2013-07-20 16:14:39 +02:00
|
|
|
int shift = tick - tickStart;
|
|
|
|
if (makeGap && !makeGap1(dstTick + shift, dstStaffIdx, Fraction::fromTicks(tickLen - shift))) {
|
|
|
|
qDebug("cannot make gap in staff %d at tick %d", dstStaffIdx, dstTick + shift);
|
|
|
|
done = true; // break main loop, cannot make gap
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
makeGap = false; // create gap only once per staff
|
2013-06-20 20:13:46 +02:00
|
|
|
}
|
2012-08-09 12:12:43 +02:00
|
|
|
else if (tag == "Tuplet") {
|
|
|
|
Tuplet* tuplet = new Tuplet(this);
|
2013-01-21 20:21:41 +01:00
|
|
|
tuplet->setTrack(e.track());
|
2013-01-11 18:10:18 +01:00
|
|
|
tuplet->read(e);
|
2013-01-21 20:21:41 +01:00
|
|
|
int tick = e.tick() - tickStart + dstTick;
|
2012-08-09 12:12:43 +02:00
|
|
|
Measure* measure = tick2measure(tick);
|
|
|
|
tuplet->setParent(measure);
|
|
|
|
tuplet->setTick(tick);
|
2013-01-21 20:21:41 +01:00
|
|
|
e.addTuplet(tuplet);
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
|
|
|
else if (tag == "Chord" || tag == "Rest" || tag == "RepeatMeasure") {
|
2013-01-18 10:55:52 +01:00
|
|
|
ChordRest* cr = static_cast<ChordRest*>(Element::name2Element(tag, this));
|
2013-01-21 20:21:41 +01:00
|
|
|
cr->setTrack(e.track());
|
2013-01-11 18:10:18 +01:00
|
|
|
cr->read(e);
|
2012-08-09 12:12:43 +02:00
|
|
|
cr->setSelected(false);
|
|
|
|
int voice = cr->voice();
|
|
|
|
int track = dstStaffIdx * VOICES + voice;
|
|
|
|
cr->setTrack(track);
|
2013-01-21 20:21:41 +01:00
|
|
|
int tick = e.tick() - tickStart + dstTick;
|
2013-06-19 16:25:29 +02:00
|
|
|
if (cr->isGrace())
|
|
|
|
graceNotes.push_back(static_cast<Chord*>(cr));
|
|
|
|
else {
|
|
|
|
e.setTick(e.tick() + cr->actualTicks());
|
|
|
|
if (cr->type() == Element::CHORD) {
|
|
|
|
Chord* chord = static_cast<Chord*>(cr);
|
|
|
|
for (int i = 0; i < graceNotes.size(); ++i) {
|
|
|
|
Chord* gc = graceNotes[i];
|
|
|
|
gc->setGraceIndex(i);
|
|
|
|
chord->add(gc);
|
|
|
|
}
|
|
|
|
graceNotes.clear();
|
|
|
|
}
|
|
|
|
pasteChordRest(cr, tick);
|
|
|
|
}
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
|
|
|
else if (tag == "HairPin"
|
|
|
|
|| tag == "Pedal"
|
|
|
|
|| tag == "Ottava"
|
|
|
|
|| tag == "Trill"
|
|
|
|
|| tag == "TextLine"
|
2013-06-10 11:03:34 +02:00
|
|
|
|| tag == "Slur"
|
2012-08-09 12:12:43 +02:00
|
|
|
|| tag == "Volta") {
|
2013-01-18 10:55:52 +01:00
|
|
|
Spanner* sp = static_cast<Spanner*>(Element::name2Element(tag, this));
|
2013-06-20 17:23:24 +02:00
|
|
|
sp->setAnchor(Spanner::ANCHOR_SEGMENT);
|
2013-10-14 11:56:54 +02:00
|
|
|
sp->read(e);
|
2013-07-29 18:06:11 +02:00
|
|
|
sp->setTrack(dstStaffIdx * VOICES);
|
2013-10-11 10:45:53 +02:00
|
|
|
sp->setTrack2(dstStaffIdx * VOICES);
|
2013-06-10 11:03:34 +02:00
|
|
|
sp->setTick(e.tick() - tickStart + dstTick);
|
2013-06-20 17:23:24 +02:00
|
|
|
addSpanner(sp);
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
|
|
|
else if (tag == "endSpanner") {
|
2013-01-11 18:10:18 +01:00
|
|
|
int id = e.intAttribute("id");
|
2013-06-20 17:23:24 +02:00
|
|
|
Spanner* spanner = findSpanner(id);
|
2013-01-17 12:56:14 +01:00
|
|
|
if (spanner) {
|
2013-06-20 17:23:24 +02:00
|
|
|
// e.spanner().removeOne(spanner);
|
2013-06-10 11:03:34 +02:00
|
|
|
spanner->setTick2(e.tick() - tickStart + dstTick);
|
2013-06-20 18:48:28 +02:00
|
|
|
removeSpanner(spanner);
|
2013-01-17 12:56:14 +01:00
|
|
|
undoAddElement(spanner);
|
|
|
|
if (spanner->type() == Element::OTTAVA) {
|
|
|
|
Ottava* o = static_cast<Ottava*>(spanner);
|
2013-07-16 09:03:47 +02:00
|
|
|
o->staff()->updateOttava(o);
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
2013-01-17 12:56:14 +01:00
|
|
|
else if (spanner->type() == Element::HAIRPIN) {
|
|
|
|
Hairpin* hp = static_cast<Hairpin*>(spanner);
|
2012-08-09 12:12:43 +02:00
|
|
|
updateHairpin(hp);
|
|
|
|
}
|
|
|
|
}
|
2013-01-17 12:56:14 +01:00
|
|
|
e.readNext();
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
|
|
|
else if (tag == "Lyrics") {
|
|
|
|
Lyrics* lyrics = new Lyrics(this);
|
2013-01-21 20:21:41 +01:00
|
|
|
lyrics->setTrack(e.track());
|
2013-01-11 18:10:18 +01:00
|
|
|
lyrics->read(e);
|
2012-08-09 12:12:43 +02:00
|
|
|
lyrics->setTrack(dstStaffIdx * VOICES);
|
2013-01-21 20:21:41 +01:00
|
|
|
int tick = e.tick() - tickStart + dstTick;
|
2012-08-09 12:12:43 +02:00
|
|
|
Segment* segment = tick2segment(tick);
|
|
|
|
if (segment) {
|
|
|
|
lyrics->setParent(segment);
|
|
|
|
undoAddElement(lyrics);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
delete lyrics;
|
|
|
|
qDebug("no segment found for lyrics");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (tag == "Harmony") {
|
|
|
|
Harmony* harmony = new Harmony(this);
|
2013-01-21 20:21:41 +01:00
|
|
|
harmony->setTrack(e.track());
|
2013-01-11 18:10:18 +01:00
|
|
|
harmony->read(e);
|
2012-08-09 12:12:43 +02:00
|
|
|
harmony->setTrack(dstStaffIdx * VOICES);
|
2013-06-18 19:11:27 +02:00
|
|
|
// transpose
|
2012-08-09 12:12:43 +02:00
|
|
|
Part* partDest = staff(dstStaffIdx)->part();
|
2013-06-18 19:11:27 +02:00
|
|
|
Interval interval = partDest->instr()->transpose();
|
|
|
|
if (!styleB(ST_concertPitch) && !interval.isZero()) {
|
|
|
|
interval.flip();
|
2012-08-09 12:12:43 +02:00
|
|
|
int rootTpc = transposeTpc(harmony->rootTpc(), interval, false);
|
|
|
|
int baseTpc = transposeTpc(harmony->baseTpc(), interval, false);
|
|
|
|
undoTransposeHarmony(harmony, rootTpc, baseTpc);
|
|
|
|
}
|
|
|
|
|
2013-01-21 20:21:41 +01:00
|
|
|
int tick = e.tick() - tickStart + dstTick;
|
2012-08-09 12:12:43 +02:00
|
|
|
Measure* m = tick2measure(tick);
|
|
|
|
Segment* seg = m->undoGetSegment(Segment::SegChordRest, tick);
|
|
|
|
harmony->setParent(seg);
|
|
|
|
undoAddElement(harmony);
|
|
|
|
}
|
|
|
|
else if (tag == "Dynamic"
|
|
|
|
|| tag == "Symbol"
|
|
|
|
|| tag == "FretDiagram"
|
|
|
|
|| tag == "Marker"
|
|
|
|
|| tag == "Jump"
|
|
|
|
|| tag == "Image"
|
|
|
|
|| tag == "Text"
|
|
|
|
|| tag == "StaffText"
|
|
|
|
|| tag == "TempoText"
|
2013-02-28 23:29:04 +01:00
|
|
|
|| tag == "FiguredBass"
|
2012-08-09 12:12:43 +02:00
|
|
|
) {
|
2013-01-18 10:55:52 +01:00
|
|
|
Element* el = Element::name2Element(tag, this);
|
2013-02-28 23:29:04 +01:00
|
|
|
el->setTrack(dstStaffIdx * VOICES); // a valid track might be necessary for el->read() to work
|
2012-08-09 12:12:43 +02:00
|
|
|
|
2013-01-21 20:21:41 +01:00
|
|
|
int tick = e.tick() - tickStart + dstTick;
|
2012-08-09 12:12:43 +02:00
|
|
|
Measure* m = tick2measure(tick);
|
|
|
|
Segment* seg = m->undoGetSegment(Segment::SegChordRest, tick);
|
2013-01-11 18:10:18 +01:00
|
|
|
el->setParent(seg);
|
|
|
|
el->read(e);
|
2012-08-09 12:12:43 +02:00
|
|
|
|
2013-02-28 23:29:04 +01:00
|
|
|
// be sure to paste the element in the destination track;
|
|
|
|
// setting track needs to be repeated, as it might have been overwritten by el->read()
|
|
|
|
el->setTrack(dstStaffIdx * VOICES);
|
2013-01-11 18:10:18 +01:00
|
|
|
undoAddElement(el);
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
|
|
|
else if (tag == "Clef") {
|
|
|
|
Clef* clef = new Clef(this);
|
2013-01-11 18:10:18 +01:00
|
|
|
clef->read(e);
|
2012-08-09 12:12:43 +02:00
|
|
|
clef->setTrack(dstStaffIdx * VOICES);
|
2013-01-21 20:21:41 +01:00
|
|
|
int tick = e.tick() - tickStart + dstTick;
|
2012-08-09 12:12:43 +02:00
|
|
|
Measure* m = tick2measure(tick);
|
|
|
|
if (m->tick() && m->tick() == tick)
|
|
|
|
m = m->prevMeasure();
|
|
|
|
Segment* segment = m->undoGetSegment(Segment::SegClef, tick);
|
|
|
|
clef->setParent(segment);
|
|
|
|
undoAddElement(clef);
|
|
|
|
}
|
|
|
|
else if (tag == "Breath") {
|
|
|
|
Breath* breath = new Breath(this);
|
2013-01-11 18:10:18 +01:00
|
|
|
breath->read(e);
|
2012-08-09 12:12:43 +02:00
|
|
|
breath->setTrack(dstStaffIdx * VOICES);
|
2013-01-21 20:21:41 +01:00
|
|
|
int tick = e.tick() - tickStart + dstTick;
|
2012-08-09 12:12:43 +02:00
|
|
|
Measure* m = tick2measure(tick);
|
|
|
|
Segment* segment = m->undoGetSegment(Segment::SegBreath, tick);
|
|
|
|
breath->setParent(segment);
|
|
|
|
undoAddElement(breath);
|
|
|
|
}
|
2013-01-22 11:38:09 +01:00
|
|
|
else if (tag == "Beam") {
|
|
|
|
Beam* beam = new Beam(this);
|
|
|
|
beam->setTrack(e.track());
|
|
|
|
beam->read(e);
|
|
|
|
beam->setParent(0);
|
|
|
|
e.addBeam(beam);
|
|
|
|
}
|
2012-08-09 12:12:43 +02:00
|
|
|
else if (tag == "BarLine") {
|
2013-01-17 12:56:14 +01:00
|
|
|
e.skipCurrentElement(); // ignore bar line
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
2013-01-22 11:42:52 +01:00
|
|
|
else {
|
|
|
|
qDebug("PasteStaff: element %s not handled", tag.toUtf8().data());
|
|
|
|
e.skipCurrentElement(); // ignore
|
|
|
|
}
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
2013-01-07 12:36:06 +01:00
|
|
|
|
2013-01-21 20:21:41 +01:00
|
|
|
foreach (Tuplet* tuplet, e.tuplets()) {
|
2012-08-09 12:12:43 +02:00
|
|
|
if (tuplet->elements().isEmpty()) {
|
|
|
|
// this should not happen and is a sign of input file corruption
|
|
|
|
qDebug("Measure:pasteStaff(): empty tuplet");
|
|
|
|
delete tuplet;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Measure* measure = tick2measure(tuplet->tick());
|
|
|
|
tuplet->setParent(measure);
|
|
|
|
tuplet->sortElements();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pasted) { //select only if we pasted something
|
|
|
|
Segment* s1 = tick2segment(dstTick);
|
|
|
|
Segment* s2 = tick2segment(dstTick + tickLen);
|
|
|
|
int endStaff = dstStaffStart + staves;
|
|
|
|
if (endStaff > nstaves())
|
|
|
|
endStaff = nstaves();
|
|
|
|
_selection.setRange(s1, s2, dstStaffStart, endStaff);
|
|
|
|
_selection.updateSelectedElements();
|
|
|
|
foreach(MuseScoreView* v, viewer)
|
|
|
|
v->adjustCanvasPosition(s1, false);
|
|
|
|
if (selection().state() != SEL_RANGE)
|
|
|
|
_selection.setState(SEL_RANGE);
|
|
|
|
}
|
|
|
|
}
|
2013-06-10 11:03:34 +02:00
|
|
|
foreach (Score* s, scoreList()) // for all parts
|
|
|
|
s->connectTies();
|
2013-07-24 10:20:15 +02:00
|
|
|
|
|
|
|
// when pasting between different staff types (pitched->tablature)
|
|
|
|
// fret/line has to be calculated:
|
|
|
|
updateNotes();
|
2012-08-09 12:12:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------
|
|
|
|
// pasteChordRest
|
|
|
|
//---------------------------------------------------------
|
|
|
|
|
|
|
|
void Score::pasteChordRest(ChordRest* cr, int tick)
|
|
|
|
{
|
|
|
|
// qDebug("pasteChordRest %s at %d", cr->name(), tick);
|
2012-09-13 18:01:34 +02:00
|
|
|
if (cr->type() == Element::CHORD) {
|
2012-08-09 12:12:43 +02:00
|
|
|
// set note track
|
|
|
|
// check if staffMove moves a note to a
|
|
|
|
// nonexistant staff
|
|
|
|
//
|
|
|
|
int track = cr->track();
|
|
|
|
Chord* c = static_cast<Chord*>(cr);
|
|
|
|
Part* part = cr->staff()->part();
|
|
|
|
int nn = (track / VOICES) + c->staffMove();
|
|
|
|
if (nn < 0 || nn >= nstaves())
|
|
|
|
c->setStaffMove(0);
|
|
|
|
if (!styleB(ST_concertPitch) && part->instr()->transpose().chromatic) {
|
|
|
|
Interval interval = part->instr()->transpose();
|
|
|
|
if (!interval.isZero()) {
|
|
|
|
interval.flip();
|
|
|
|
foreach(Note* n, c->notes()) {
|
|
|
|
int npitch;
|
|
|
|
int ntpc;
|
|
|
|
transposeInterval(n->pitch(), n->tpc(), &npitch, &ntpc, interval, true);
|
|
|
|
n->setPitch(npitch, ntpc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Measure* measure = tick2measure(tick);
|
2013-06-19 16:25:29 +02:00
|
|
|
if (!measure)
|
2012-08-09 12:12:43 +02:00
|
|
|
return;
|
|
|
|
|
2013-06-19 16:25:29 +02:00
|
|
|
int measureEnd = measure->endTick();
|
|
|
|
bool isGrace = (cr->type() == Element::CHORD) && (((Chord*)cr)->noteType() != NOTE_NORMAL);
|
2012-08-09 12:12:43 +02:00
|
|
|
if (!isGrace && (tick + cr->actualTicks() > measureEnd)) {
|
2012-09-13 18:01:34 +02:00
|
|
|
if (cr->type() == Element::CHORD) {
|
2012-08-09 12:12:43 +02:00
|
|
|
// split Chord
|
|
|
|
Chord* c = static_cast<Chord*>(cr);
|
|
|
|
int rest = c->actualTicks();
|
|
|
|
int len = measureEnd - tick;
|
|
|
|
rest -= len;
|
|
|
|
TDuration d;
|
|
|
|
d.setVal(len);
|
|
|
|
c->setDurationType(d);
|
|
|
|
c->setDuration(d.fraction());
|
|
|
|
undoAddCR(c, measure, tick);
|
|
|
|
while (rest) {
|
|
|
|
tick += c->actualTicks();
|
|
|
|
measure = tick2measure(tick);
|
|
|
|
if (measure->tick() != tick) { // last measure
|
|
|
|
qDebug("==last measure %d != %d", measure->tick(), tick);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Chord* c2 = static_cast<Chord*>(c->clone());
|
|
|
|
len = measure->ticks() > rest ? rest : measure->ticks();
|
|
|
|
TDuration d;
|
|
|
|
d.setVal(len);
|
|
|
|
c2->setDurationType(d);
|
|
|
|
rest -= len;
|
|
|
|
undoAddCR(c2, measure, tick);
|
|
|
|
|
|
|
|
QList<Note*> nl1 = c->notes();
|
|
|
|
QList<Note*> nl2 = c2->notes();
|
|
|
|
|
|
|
|
for (int i = 0; i < nl1.size(); ++i) {
|
|
|
|
Tie* tie = new Tie(this);
|
|
|
|
tie->setStartNote(nl1[i]);
|
|
|
|
tie->setEndNote(nl2[i]);
|
|
|
|
tie->setTrack(c->track());
|
|
|
|
Tie* tie2 = nl1[i]->tieFor();
|
|
|
|
if (tie2) {
|
|
|
|
nl2[i]->setTieFor(nl1[i]->tieFor());
|
|
|
|
tie2->setStartNote(nl2[i]);
|
|
|
|
}
|
|
|
|
nl1[i]->setTieFor(tie);
|
|
|
|
nl2[i]->setTieBack(tie);
|
|
|
|
}
|
|
|
|
c = c2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// split Rest
|
|
|
|
Rest* r = static_cast<Rest*>(cr);
|
|
|
|
Fraction rest = r->duration();
|
|
|
|
|
|
|
|
while (!rest.isZero()) {
|
|
|
|
Rest* r2 = static_cast<Rest*>(r->clone());
|
|
|
|
measure = tick2measure(tick);
|
|
|
|
Fraction mlen = Fraction::fromTicks(measure->tick() + measure->ticks() - tick);
|
|
|
|
Fraction len = rest > mlen ? mlen : rest;
|
|
|
|
r2->setDuration(len);
|
|
|
|
r2->setDurationType(TDuration(len));
|
|
|
|
undoAddCR(r2, measure, tick);
|
|
|
|
rest -= len;
|
|
|
|
tick += r2->actualTicks();
|
|
|
|
}
|
|
|
|
delete r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
undoAddCR(cr, measure, tick);
|
|
|
|
}
|
|
|
|
}
|
2013-01-23 14:14:09 +01:00
|
|
|
|
2013-05-13 18:49:17 +02:00
|
|
|
}
|
|
|
|
|