Skip to content

Commit

Permalink
fix #24759
Browse files Browse the repository at this point in the history
  • Loading branch information
wschweer committed May 14, 2014
1 parent f243191 commit 65af8f7
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 114 deletions.
168 changes: 82 additions & 86 deletions libmscore/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,7 @@ Note* Score::addNote(Chord* chord, NoteVal& noteVal)

//---------------------------------------------------------
// rewriteMeasures
// rewrite all measures up to the next time signature
// or section break
// rewrite all measures from fm to lm
//---------------------------------------------------------

bool Score::rewriteMeasures(Measure* fm, Measure* lm, const Fraction& ns)
Expand All @@ -377,58 +376,58 @@ bool Score::rewriteMeasures(Measure* fm, Measure* lm, const Fraction& ns)
++measures;

ScoreRange range;
range.read(fm->first(), lm->last(), 0, nstaves() * VOICES);
range.read(fm->first(), lm->last());
if (!range.canWrite(ns))
return false;

undoRemoveMeasures(fm, lm);
//
// calculate number of required measures = nm
//
Fraction k = range.duration();
k /= ns;
int nm = (k.numerator() + k.denominator() - 1)/ k.denominator();
Fraction k = range.duration() / ns;
int nm = (k.numerator() + k.denominator() - 1)/ k.denominator();

Fraction nd(nm * ns.numerator(), ns.denominator()); // total new duration

// evtl. we have to fill the last measure
Fraction fill = nd - range.duration();
if (!fill.isZero())
range.fill(fill);

Measure* nfm = 0;
Measure* nlm = 0;

// create destination measures
int tick = 0;
bool endBarGenerated = fm->endBarLineGenerated();
for (int i = 0; i < nm; ++i) {
Measure* m = new Measure(this);
m->setPrev(nlm);
if (nlm)
nlm->setNext(m);
m->setTimesig(ns);
m->setLen(ns);
m->setTick(tick);
m->setEndBarLineType(NORMAL_BAR, endBarGenerated);
tick += m->ticks();
nlm = m;
if (nfm == 0)
nfm = m;
}
if (!range.write(0, nfm)) {
qFatal("Cannot write measures\n");
range.fill(fill);

for (Score* s : scoreList()) {
Measure* m1 = s->tick2measure(fm->tick());
Measure* m2 = s->tick2measure(lm->tick());
s->undoRemoveMeasures(m1, m2);

Measure* nlm = 0;
Measure* nfm = 0;
int tick = 0;
bool endBarGenerated = m1->endBarLineGenerated();
for (int i = 0; i < nm; ++i) {
Measure* m = new Measure(s);
m->setPrev(nlm);
if (nlm)
nlm->setNext(m);
m->setTimesig(ns);
m->setLen(ns);
m->setTick(tick);
m->setEndBarLineType(NORMAL_BAR, endBarGenerated);
tick += m->ticks();
nlm = m;
if (nfm == 0)
nfm = m;
}
nlm->setEndBarLineType(m2->endBarLineType(), m2->endBarLineGenerated(),
m2->endBarLineVisible(), m2->endBarLineColor());
//
// insert new calculated measures
//
nfm->setPrev(m1->prev());
nlm->setNext(m2->next());
s->undo(new InsertMeasures(nfm, nlm));
}
nlm->setEndBarLineType(lm->endBarLineType(), lm->endBarLineGenerated(),
lm->endBarLineVisible(), lm->endBarLineColor());

//
// insert new calculated measures
//
nfm->setPrev(fm->prev());
nlm->setNext(lm->next());
undo(new InsertMeasures(nfm, nlm));
range.fixup(nfm);
if (!range.write(rootScore(), fm->tick()))
qFatal("Cannot write measures");

return true;
}

Expand Down Expand Up @@ -502,7 +501,6 @@ void Score::cmdAddTimeSig(Measure* fm, int staffIdx, TimeSig* ts, bool local)
TimeSig* lts = staff(staffIdx)->timeSig(tick);
Fraction stretch;
Fraction lsig; // last signature
bool written = true;
if (lts) {
stretch = lts->stretch();
lsig = lts->sig();
Expand Down Expand Up @@ -537,14 +535,9 @@ void Score::cmdAddTimeSig(Measure* fm, int staffIdx, TimeSig* ts, bool local)
return;
}

foreach(Score* score, scoreList()) {
Measure* fm = score->tick2measure(tick);
Measure* nfm = fm;
if (ots && ots->sig() == ts->sig() && ots->stretch() == ts->stretch()) {
//
// Set time signature of all measures up to next
// time signature. Do not touch measure contents.
//
if (ots && ots->sig() == ts->sig() && ots->stretch() == ts->stretch()) {
foreach (Score* score, scoreList()) {
Measure* fm = score->tick2measure(tick);
for (Measure* m = fm; m; m = m->nextMeasure()) {
if ((m != fm) && m->first(Segment::SegTimeSig))
break;
Expand All @@ -554,46 +547,49 @@ void Score::cmdAddTimeSig(Measure* fm, int staffIdx, TimeSig* ts, bool local)
undoChangeProperty(m, P_TIMESIG_ACTUAL, QVariant::fromValue(ns));
}
}
}
else {
Score* score = rootScore();
Measure* fm = score->tick2measure(tick);
//
// rewrite all measures up to the next time signature
//
if (fm == score->firstMeasure() && (fm->len() != fm->timesig())) {
// handle upbeat
undoChangeProperty(fm, P_TIMESIG_NOMINAL, QVariant::fromValue(ns));
Measure* m = fm->nextMeasure();
Segment* s = m->findSegment(Segment::SegTimeSig, m->tick());
fm = s ? 0 : fm->nextMeasure();
}
else {
//
// rewrite all measures up to the next time signature
//
if (fm == firstMeasure() && (fm->len() != fm->timesig())) {
// handle upbeat
undoChangeProperty(fm, P_TIMESIG_NOMINAL, QVariant::fromValue(ns));
Measure* m = fm->nextMeasure();
Segment* s = m->findSegment(Segment::SegTimeSig, m->tick());
if (!s) {
// there is something to rewrite
written = score->rewriteMeasures(fm->nextMeasure(), ns);
}
}
else {
if (_sigmap->timesig(seg->tick()).timesig() != ts->sig()) {
written = score->rewriteMeasures(fm, ns);
nfm = fm->prev() ? fm->prev()->nextMeasure() : firstMeasure();
}
if (sigmap()->timesig(seg->tick()).timesig() == ts->sig())
fm = 0;
}
if (fm) {
if (!score->rewriteMeasures(fm, ns)) {
delete ts;
return;
}
}

if(!written)
break;

seg = nfm->undoGetSegment(Segment::SegTimeSig, nfm->tick());
int n = score->nstaves();
for (int staffIdx = 0; staffIdx < n; ++staffIdx) {
TimeSig* nsig = static_cast<TimeSig*>(seg->element(staffIdx * VOICES));
if (nsig == 0) {
nsig = new TimeSig(this);
nsig->setTrack(staffIdx * VOICES);
nsig->setParent(seg);
nsig->setSig(ts->sig(), ts->timeSigType());
undoAddElement(nsig);
}
else {
undo(new ChangeTimesig(nsig, false, ts->sig(), ts->stretch(),
ts->numeratorString(), ts->denominatorString(), ts->timeSigType()));
nsig->setDropTarget(0); // DEBUG
foreach (Score* score, scoreList()) {
Measure* nfm = score->tick2measure(tick);
seg = nfm->undoGetSegment(Segment::SegTimeSig, nfm->tick());
int n = score->nstaves();
for (int staffIdx = 0; staffIdx < n; ++staffIdx) {
TimeSig* nsig = static_cast<TimeSig*>(seg->element(staffIdx * VOICES));
if (nsig == 0) {
nsig = new TimeSig(score);
nsig->setTrack(staffIdx * VOICES);
nsig->setParent(seg);
nsig->setSig(ts->sig(), ts->timeSigType());
undoAddElement(nsig);
}
else {
undo(new ChangeTimesig(nsig, false, ts->sig(), ts->stretch(),
ts->numeratorString(), ts->denominatorString(), ts->timeSigType()));
nsig->setDropTarget(0); // DEBUG
}
}
}
}
Expand Down
140 changes: 138 additions & 2 deletions libmscore/excerpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,13 +424,12 @@ void cloneStaves(Score* oscore, Score* score, const QList<int>& map)

//---------------------------------------------------------
// cloneStaff
// srcStaff and dstStaff are in the same score
// staves are in same score
//---------------------------------------------------------

void cloneStaff(Staff* srcStaff, Staff* dstStaff)
{
Score* score = srcStaff->score();

TieMap tieMap;

int srcStaffIdx = score->staffIdx(srcStaff);
Expand All @@ -455,6 +454,7 @@ void cloneStaff(Staff* srcStaff, Staff* dstStaff)
ne = oe->linkedClone();
ne->setTrack(dstTrack);
ne->setParent(seg);
ne->setScore(score);
score->undoAddElement(ne);
if (oe->isChordRest()) {
ChordRest* ocr = static_cast<ChordRest*>(oe);
Expand Down Expand Up @@ -490,6 +490,7 @@ void cloneStaff(Staff* srcStaff, Staff* dstStaff)
Element* ne = e->clone();
ne->setTrack(dstTrack);
ne->setParent(seg);
ne->setScore(score);
score->undoAddElement(ne);
}
}
Expand Down Expand Up @@ -547,5 +548,140 @@ void cloneStaff(Staff* srcStaff, Staff* dstStaff)
}
}

//---------------------------------------------------------
// cloneStaff2
// staves are in different scores
//---------------------------------------------------------

void cloneStaff2(Staff* srcStaff, Staff* dstStaff, int stick, int etick)
{
Score* oscore = srcStaff->score();
Score* score = dstStaff->score();
Measure* m1 = oscore->tick2measure(stick);
Measure* m2 = oscore->tick2measure(etick);

TieMap tieMap;

int srcStaffIdx = oscore->staffIdx(srcStaff);
int dstStaffIdx = score->staffIdx(dstStaff);

for (Measure* m = m1; m != m2; m = m->nextMeasure()) {
Measure* nm = score->tick2measure(m->tick());
int sTrack = srcStaffIdx * VOICES;
int eTrack = sTrack + VOICES;
for (int srcTrack = sTrack; srcTrack < eTrack; ++srcTrack) {
TupletMap tupletMap; // tuplets cannot cross measure boundaries
int dstTrack = dstStaffIdx * VOICES + (srcTrack - sTrack);
for (Segment* oseg = m->first(); oseg; oseg = oseg->next()) {
Element* oe = oseg->element(srcTrack);
if (oe == 0 || oe->generated())
continue;
if (oe->type() == Element::TIMESIG)
continue;
Segment* ns = nm->getSegment(oseg->segmentType(), oseg->tick());
Element* ne;
if (oe->type() == Element::CLEF)
ne = oe->clone();
else
ne = oe->linkedClone();
ne->setTrack(dstTrack);
ne->setParent(ns);
ne->setScore(score);
score->undoAddElement(ne);
if (oe->isChordRest()) {
ChordRest* ocr = static_cast<ChordRest*>(oe);
ChordRest* ncr = static_cast<ChordRest*>(ne);
Tuplet* ot = ocr->tuplet();
if (ot) {
Tuplet* nt = tupletMap.findNew(ot);
if (nt == 0) {
nt = new Tuplet(*ot);
nt->clear();
nt->setTrack(dstTrack);
nt->setParent(m);
tupletMap.add(ot, nt);
}
ncr->setTuplet(nt);
nt->add(ncr);
}
foreach (Element* e, oseg->annotations()) {
if (e->generated() || e->systemFlag())
continue;
if (e->track() != srcTrack)
continue;
switch (e->type()) {
// exclude certain element types
// this should be same list excluded in Score::undoAddElement()
case Element::STAFF_TEXT:
case Element::HARMONY:
case Element::FIGURED_BASS:
case Element::LYRICS:
case Element::DYNAMIC:
continue;
default:
Element* ne = e->clone();
ne->setTrack(dstTrack);
ne->setParent(ns);
ne->setScore(score);
score->undoAddElement(ne);
}
}
if (oe->type() == Element::CHORD) {
Chord* och = static_cast<Chord*>(ocr);
Chord* nch = static_cast<Chord*>(ncr);
int n = och->notes().size();
for (int i = 0; i < n; ++i) {
Note* on = och->notes().at(i);
Note* nn = nch->notes().at(i);
if (on->tieFor()) {
Tie* tie = new Tie(score);
nn->setTieFor(tie);
tie->setStartNote(nn);
tie->setTrack(nn->track());
tieMap.add(on->tieFor(), tie);
}
if (on->tieBack()) {
Tie* tie = tieMap.findNew(on->tieBack());
if (tie) {
nn->setTieBack(tie);
tie->setEndNote(nn);
}
else {
qDebug("cloneStave: cannot find tie");
}
}
}
}
}
}
}
}

for (auto i : oscore->spanner()) {
Spanner* s = i.second;
if (!(s->tick() >= stick && s->tick2() < etick))
continue;

int staffIdx = s->staffIdx();
int dstTrack = -1;
int dstTrack2 = -1;
if (s->type() != Element::VOLTA) {
//export other spanner if staffidx matches
if (srcStaffIdx == staffIdx) {
dstTrack = dstStaffIdx * VOICES + s->voice();
dstTrack2 = dstStaffIdx * VOICES + (s->track2() % VOICES);
}
}
if (dstTrack == -1)
continue;
Spanner* ns = static_cast<Spanner*>(s->linkedClone());
ns->setScore(score);
ns->setParent(0);
ns->setTrack(dstTrack);
ns->setTrack2(dstTrack2);
score->addSpanner(ns);
}
}

}

1 change: 1 addition & 0 deletions libmscore/excerpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Excerpt {
extern Score* createExcerpt(const QList<Part*>&);
extern void cloneStaves(Score* oscore, Score* score, const QList<int>& map);
extern void cloneStaff(Staff* ostaff, Staff* nstaff);
extern void cloneStaff2(Staff* ostaff, Staff* nstaff, int stick, int etick);


} // namespace Ms
Expand Down
Loading

0 comments on commit 65af8f7

Please sign in to comment.