Merge pull request #2656 from Rockettwo/excerptsdialog-singleforeveryVoice

New Excerptsdialog with linked voices
This commit is contained in:
Nicolas Froment 2016-09-14 10:38:01 +02:00 committed by GitHub
commit c282a23b62
29 changed files with 4697 additions and 976 deletions

View file

@ -56,6 +56,7 @@
#include "ottava.h"
#include "textframe.h"
#include "accidental.h"
#include "tremolo.h"
namespace Ms {
@ -1258,6 +1259,10 @@ void Score::putNote(const Position& p, bool replace, bool insert)
_is.setTrack(staffIdx * VOICES + _is.voice());
_is.setSegment(s);
if (score()->excerpt() && !score()->excerpt()->tracks().isEmpty()
&& score()->excerpt()->tracks().key(_is.track(), -1) == -1)
return;
Direction stemDirection = Direction::AUTO;
bool error;
NoteVal nval = noteValForPosition(p, error);
@ -1952,6 +1957,11 @@ void Score::deleteItem(Element* el)
undoRemoveElement(rest->tuplet());
if (el->voice() != 0) {
rest->undoChangeProperty(P_ID::GAP, true);
for (ScoreElement* r : el->linkList()) {
Rest* rest = static_cast<Rest*>(r);
if (rest->track() % VOICES)
rest->undoChangeProperty(P_ID::GAP, true);
}
// delete them really when only gap rests are in the actual measure.
Measure* m = toRest(el)->measure();
@ -2018,12 +2028,18 @@ void Score::deleteItem(Element* el)
Fraction f = Fraction::fromTicks(ticks);
Rest* rest = new Rest(score());
rest->setDuration(f);
rest->setTrack(track);
Segment* segment = m->getSegment(rest, stick);
segment->add(rest);
rest->setGap(true);
std::vector<TDuration> dList = toDurationList(f, true);
if (dList.empty())
break;
for (const TDuration& d : dList) {
Rest* rest = new Rest(this);
rest->setDuration(d.fraction());
rest->setDurationType(d);
rest->setTrack(track);
rest->setGap(true);
undoAddCR(rest, m, stick);
}
}
}
// Set input position
@ -2821,6 +2837,10 @@ void Score::cmdExchangeVoice(int s, int d)
Measure* m1 = tick2measure(t1);
Measure* m2 = tick2measure(t2);
if (selection().score()->excerpt())
return;
if (t2 > m2->tick())
m2 = 0;
@ -3424,4 +3444,270 @@ void Score::timeDelete(Measure* m, Segment* startSegment, const Fraction& f)
s->undoChangeProperty(P_ID::TICK, s->rtick() - len);
undo(new ChangeMeasureLen(m, m->len() - f));
}
//---------------------------------------------------------
// cloneVoice
//---------------------------------------------------------
void Score::cloneVoice(int strack, int dtrack, Segment* sf, int lTick, bool link, bool spanner)
{
int start = sf->tick();
TieMap tieMap;
TupletMap tupletMap; // tuplets cannot cross measure boundaries
Score* score = sf->score();
Tremolo* tremolo = 0;
for (Segment* oseg = sf; oseg && oseg->tick() < lTick; oseg = oseg->next1()) {
Segment* ns = nullptr; //create segment later, on demand
Measure* dm = tick2measure(oseg->tick());
Element* oe = oseg->element(strack);
if (oe && !oe->generated() && oe->isChordRest()) {
Element* ne;
//does a linked clone to create just this element
//otherwise element will be add in every linked stave
if (link)
ne = oe->linkedClone();
else
ne = oe->clone();
ne->setTrack(dtrack);
//Don't clone gaps to a first voice
if (!(ne->track() % VOICES) && ne->isRest())
toRest(ne)->setGap(false);
ne->setScore(this);
ChordRest* ocr = toChordRest(oe);
ChordRest* ncr = toChordRest(ne);
//Handle beams
if (ocr->beam() && !ocr->beam()->empty() && ocr->beam()->elements().front() == ocr) {
Beam* nb = ocr->beam()->clone();
nb->clear();
nb->setTrack(dtrack);
nb->setScore(this);
nb->add(ncr);
ncr->setBeam(nb);
}
// clone Tuplets
Tuplet* ot = ocr->tuplet();
if (ot) {
ot->setTrack(strack);
Tuplet* nt = tupletMap.findNew(ot);
if (nt == 0) {
if (link)
nt = toTuplet(ot->linkedClone());
else
nt = toTuplet(ot->clone());
nt->setTrack(dtrack);
nt->setParent(dm);
tupletMap.add(ot, nt);
Tuplet* nt1 = nt;
while (ot->tuplet()) {
Tuplet* nt = tupletMap.findNew(ot->tuplet());
if (nt == 0) {
if (link)
nt = toTuplet(ot->tuplet()->linkedClone());
else
nt = toTuplet(ot->tuplet()->clone());
nt->setTrack(dtrack);
nt->setParent(dm);
tupletMap.add(ot->tuplet(), nt);
}
nt->add(nt1);
nt1->setTuplet(nt);
ot = ot->tuplet();
nt1 = nt;
}
}
nt->add(ncr);
ncr->setTuplet(nt);
}
// clone additional settings
if (oe->isChordRest()) {
if (oe->isRest()) {
Rest* ore = toRest(ocr);
// If we would clone a full measure rest just don't clone this rest
if (ore->isFullMeasureRest() && (dtrack % VOICES)) {
continue;
}
}
if (oe->isChord()) {
Chord* och = toChord(ocr);
Chord* nch = toChord(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);
Interval v = staff(dtrack) ? staff(dtrack)->part()->instrument(dtrack)->transpose() : Interval();
nn->setTpc1(on->tpc1());
if (v.isZero())
nn->setTpc2(on->tpc1());
else {
v.flip();
nn->setTpc2(Ms::transposeTpc(nn->tpc1(), v, true));
}
if (on->tieFor()) {
Tie* tie;
if (link)
tie = toTie(on->tieFor()->linkedClone());
else
tie = toTie(on->tieFor()->clone());
tie->setScore(this);
nn->setTieFor(tie);
tie->setStartNote(nn);
tie->setTrack(nn->track());
tie->setEndNote(nn);
tieMap.add(on->tieFor(), tie);
}
if (on->tieBack()) {
Tie* tie = tieMap.findNew(on->tieBack());
if (tie) {
nn->setTieBack(tie);
tie->setEndNote(nn);
}
else {
qDebug("cloneVoices: cannot find tie");
}
}
// add back spanners (going back from end to start spanner element
// makes sure the 'other' spanner anchor element is already set up)
// 'on' is the old spanner end note and 'nn' is the new spanner end note
for (Spanner* oldSp : on->spannerBack()) {
Note* newStart = Spanner::startElementFromSpanner(oldSp, nn);
if (newStart != nullptr) {
Spanner* newSp;
if (link)
newSp = static_cast<Spanner*>(oldSp->linkedClone());
else
newSp = static_cast<Spanner*>(oldSp->clone());
newSp->setNoteSpan(newStart, nn);
addElement(newSp);
}
else {
qDebug("cloneVoices: cannot find spanner start note");
}
}
}
// two note tremolo
if (och->tremolo() && och->tremolo()->twoNotes()) {
if (och == och->tremolo()->chord1()) {
if (tremolo)
qDebug("unconnected two note tremolo");
if (link)
tremolo = toTremolo(och->tremolo()->linkedClone());
else
tremolo = toTremolo(och->tremolo()->clone());
tremolo->setScore(nch->score());
tremolo->setParent(nch);
tremolo->setTrack(nch->track());
tremolo->setChords(nch, 0);
nch->setTremolo(tremolo);
}
else if (och == och->tremolo()->chord2()) {
if (!tremolo)
qDebug("first note for two note tremolo missing");
else {
tremolo->setChords(tremolo->chord1(), nch);
nch->setTremolo(tremolo);
}
}
else
qDebug("inconsistent two note tremolo");
}
}
// Add element (link -> just in this measure)
if (link) {
if (!ns)
ns = dm->getSegment(oseg->segmentType(), oseg->tick());
ns->add(ne);
}
else {
undoAddCR(toChordRest(ne), dm, oseg->tick());
}
}
}
Segment* tst = dm->segments().firstCRSegment();
if (strack % VOICES && !(dtrack % VOICES) && (!tst || (!tst->element(dtrack)))) {
Rest* rest = new Rest(this);
rest->setDuration(dm->len());
rest->setDurationType(TDuration::DurationType::V_MEASURE);
rest->setTrack(dtrack);
if (link) {
Segment* segment = dm->getSegment(rest, dm->tick());
segment->add(rest);
}
else
undoAddCR(toChordRest(rest), dm, dm->tick());
}
}
if (spanner) {
// Find and add corresponding slurs
auto spanners = score->spannerMap().findOverlapping(start, lTick);
for (auto i = spanners.begin(); i < spanners.end(); i++) {
Spanner* sp = i->value;
int spStart = sp->tick();
int track = sp->track();
int track2 = sp->track2();
int spEnd = spStart + sp->ticks();
qDebug("Start %d End %d Diff %d \n Measure Start %d End %d", spStart, spEnd, spEnd-spStart, start, lTick);
if (sp->isSlur() && (spStart >= start && spEnd < lTick)) {
if (track == strack && track2 == strack){
Spanner* ns;
if (link)
ns = static_cast<Spanner*>(sp->linkedClone());
else
ns = static_cast<Spanner*>(sp->clone());
ns->setScore(this);
ns->setParent(0);
ns->setTrack(dtrack);
ns->setTrack2(dtrack);
// set start/end element for slur
ChordRest* cr1 = sp->startCR();
ChordRest* cr2 = sp->endCR();
ns->setStartElement(0);
ns->setEndElement(0);
if (cr1 && cr1->links()) {
for (ScoreElement* e : *cr1->links()) {
ChordRest* cr = static_cast<ChordRest*>(e);
if (cr == cr1)
continue;
if ((cr->score() == this) && (cr->tick() == ns->tick()) && cr->track() == dtrack) {
ns->setStartElement(cr);
break;
}
}
}
if (cr2 && cr2->links()) {
for (ScoreElement* e : *cr2->links()) {
ChordRest* cr = static_cast<ChordRest*>(e);
if (cr == cr2)
continue;
if ((cr->score() == this) && (cr->tick() == ns->tick2()) && cr->track() == dtrack) {
ns->setEndElement(cr);
break;
}
}
}
undo(new AddElement(ns));
}
}
}
}
//Layout
doLayoutRange(start, lTick);
}
}

View file

@ -82,6 +82,8 @@ bool Excerpt::operator!=(const Excerpt& e) const
return true;
if (e._parts != _parts)
return true;
if (e._tracks != _tracks)
return true;
return false;
}
@ -97,6 +99,8 @@ bool Excerpt::operator==(const Excerpt& e) const
return false;
if (e._parts != _parts)
return false;
if (e._tracks != _tracks)
return false;
return true;
}
@ -133,6 +137,7 @@ void createExcerpt(Excerpt* excerpt)
score->setPageNumberOffset(oscore->pageNumberOffset());
// Set instruments and create linked staffs
foreach (Part* part, parts) {
Part* p = new Part(score);
p->setInstrument(*part->instrument());
@ -141,6 +146,7 @@ void createExcerpt(Excerpt* excerpt)
foreach (Staff* staff, *part->staves()) {
Staff* s = new Staff(score);
s->setPart(p);
s->setExcerpt(excerpt);
s->setStaffType(staff->staffType());
s->setDefaultClefType(staff->defaultClefType());
score->undo(new LinkStaff(s, staff));
@ -150,20 +156,35 @@ void createExcerpt(Excerpt* excerpt)
}
score->appendPart(p);
}
cloneStaves(oscore, score, srcStaves);
//
// create excerpt title
//
// Fill tracklist (map all tracks of a stave)
if (excerpt->tracks().isEmpty()) {
QMultiMap<int, int> tracks;
for (Staff* s : score->staves()) {
LinkedStaves* ls = s->linkedStaves();
if (ls == 0)
continue;
for (Staff* ps : ls->staves()) {
if (ps->primaryStaff()) {
for (int i = 0; i < VOICES; i++)
tracks.insert(ps->idx() * VOICES + i % VOICES, s->idx() * VOICES + i % VOICES);
break;
}
}
}
excerpt->setTracks(tracks);
}
cloneStaves(oscore, score, srcStaves, excerpt->tracks());
// create excerpt title and title frame for all scores if not already there
MeasureBase* measure = oscore->first();
// create title frame for all scores if not already there
if (!measure || (measure->type() != Element::Type::VBOX))
measure = oscore->insertMeasure(Element::Type::VBOX, measure);
VBox* titleFrameScore = static_cast<VBox*>(measure);
measure = score->first();
measure = score->first();
Q_ASSERT(measure->type() == Element::Type::VBOX);
VBox* titleFramePart = static_cast<VBox*>(measure);
@ -178,18 +199,16 @@ void createExcerpt(Excerpt* excerpt)
score->setMetaTag("partName", partLabel);
}
//
// layout score
//
score->addLayoutFlags(LayoutFlag::FIX_PITCH_VELO);
score->doLayout();
//
// handle transposing instruments
//
if (oscore->styleB(StyleIdx::concertPitch) != score->styleB(StyleIdx::concertPitch)) {
for (Staff* staff : score->staves()) {
if (staff->staffType()->group() == StaffGroup::PERCUSSION)
continue;
// if this staff has no transposition, and no instrument changes, we can skip it
Interval interval = staff->part()->instrument()->transpose();
if (interval.isZero() && staff->part()->instruments()->size() == 1)
@ -228,9 +247,7 @@ void createExcerpt(Excerpt* excerpt)
}
}
//
// layout score
//
score->setPlaylistDirty();
oscore->rebuildMidiMapping();
oscore->updateChannel();
@ -239,6 +256,10 @@ void createExcerpt(Excerpt* excerpt)
score->doLayout();
}
//---------------------------------------------------------
// deleteExcerpt
//---------------------------------------------------------
void deleteExcerpt(Excerpt* excerpt)
{
MasterScore* oscore = excerpt->oscore();
@ -303,10 +324,10 @@ static void cloneSpanner(Spanner* s, Score* score, int dstTrack, int dstTrack2)
ns->setParent(0);
ns->setTrack(dstTrack);
ns->setTrack2(dstTrack2);
if (ns->type() == Element::Type::SLUR) {
//
// set start/end element for slur
//
ChordRest* cr1 = s->startCR();
ChordRest* cr2 = s->endCR();
@ -375,31 +396,11 @@ static void cloneTuplets(ChordRest* ocr, ChordRest* ncr, Tuplet* ot, TupletMap&
ncr->setTuplet(nt);
}
//---------------------------------------------------------
// mapTrack
//---------------------------------------------------------
static int mapTrack(int srcTrack, const QList<int>& map)
{
if (srcTrack == -1)
return -1;
int track = -1;
int st = 0;
foreach(int staff, map) {
if (staff == srcTrack / VOICES) {
track = (st * VOICES) + srcTrack % VOICES;
break;
}
++st;
}
return track;
}
//---------------------------------------------------------
// cloneStaves
//---------------------------------------------------------
void cloneStaves(Score* oscore, Score* score, const QList<int>& map)
void cloneStaves(Score* oscore, Score* score, const QList<int>& map, QMultiMap<int, int>& trackList)
{
TieMap tieMap;
@ -446,7 +447,7 @@ void cloneStaves(Score* oscore, Score* score, const QList<int>& map)
for (int srcTrack = 0; srcTrack < tracks; ++srcTrack) {
TupletMap tupletMap; // tuplets cannot cross measure boundaries
int track = mapTrack(srcTrack, map);
int track = trackList.value(srcTrack, -1);
Tremolo* tremolo = 0;
for (Segment* oseg = m->first(); oseg; oseg = oseg->next()) {
@ -458,8 +459,8 @@ void cloneStaves(Score* oscore, Score* score, const QList<int>& map)
|| (e->systemFlag() && srcTrack == 0)
) {
Element* ne = e->linkedClone();
ne->setUserOff(QPointF()); // reset user offset as most likely
// it will not fit
// reset user offset as most likely it will not fit
ne->setUserOff(QPointF());
ne->setReadPos(QPointF());
ne->setTrack(track == -1 ? 0 : track);
ne->setScore(score);
@ -475,142 +476,173 @@ void cloneStaves(Score* oscore, Score* score, const QList<int>& map)
}
}
if (track == -1)
//If track is not mapped skip the following
if (trackList.value(srcTrack, -1) == -1)
continue;
Element* oe = oseg->element(srcTrack);
int adjustedBarlineSpan = 0;
if (srcTrack % VOICES == 0 && oseg->segmentType() == Segment::Type::BarLine) {
// mid-measure barline segment
// may need to clone barline from a previous staff and/or adjust span
int oIdx = srcTrack / VOICES;
if (!oe) {
// no barline on this staff in original score,
// but check previous staves
for (int i = oIdx - 1; i >= 0; --i) {
oe = oseg->element(i * VOICES);
if (oe)
break;
//There are probably more destination tracks for the same source
QList<int> t = trackList.values(srcTrack);
for (int track : t) {
//Clone KeySig TimeSig and Clefs if voice 1 of source staff is not mapped to a track
Element* oef = oseg->element(srcTrack & ~3);
if (oef && (oef->isTimeSig() || oef->isKeySig()) && oef->tick() == 0
&& !(trackList.size() == (score->excerpt()->parts().size() * VOICES))) {
Element* ne = oef->linkedClone();
ne->setTrack(track & ~3);
ne->setScore(score);
ns = nm->getSegment(oseg->segmentType(), oseg->tick());
ns->add(ne);
}
Element* oe = oseg->element(srcTrack);
int adjustedBarlineSpan = 0;
if (srcTrack % VOICES == 0 && oseg->segmentType() == Segment::Type::BarLine) {
// mid-measure barline segment
// may need to clone barline from a previous staff and/or adjust span
int oIdx = srcTrack / VOICES;
if (!oe) {
// no barline on this staff in original score,
// but check previous staves
for (int i = oIdx - 1; i >= 0; --i) {
oe = oseg->element(i * VOICES);
if (oe)
break;
}
}
if (oe) {
// barline found, now check span
BarLine* bl = static_cast<BarLine*>(oe);
int oSpan1 = bl->staff()->idx();
int oSpan2 = oSpan1 + bl->span();
if (oSpan1 <= oIdx && oIdx < oSpan2) {
// this staff is within span
// calculate adjusted span for excerpt
int oSpan = oSpan2 - oIdx;
adjustedBarlineSpan = qMin(oSpan, score->nstaves());
}
else {
// this staff is not within span
oe = nullptr;
}
}
}
if (oe) {
// barline found, now check span
BarLine* bl = static_cast<BarLine*>(oe);
int oSpan1 = bl->staff()->idx();
int oSpan2 = oSpan1 + bl->span();
if (oSpan1 <= oIdx && oIdx < oSpan2) {
// this staff is within span
// calculate adjusted span for excerpt
int oSpan = oSpan2 - oIdx;
adjustedBarlineSpan = qMin(oSpan, score->nstaves());
if (oe && !oe->generated()) {
Element* ne;
ne = oe->linkedClone();
ne->setTrack(track);
if (!(ne->track() % VOICES) && ne->isRest())
toRest(ne)->setGap(false);
ne->scanElements(score, localSetScore); //necessary?
ne->setScore(score);
if (oe->type() == Element::Type::BAR_LINE && adjustedBarlineSpan) {
BarLine* nbl = static_cast<BarLine*>(ne);
nbl->setSpan(adjustedBarlineSpan);
}
else {
// this staff is not within span
oe = nullptr;
else if (oe->isChordRest()) {
ChordRest* ocr = static_cast<ChordRest*>(oe);
ChordRest* ncr = static_cast<ChordRest*>(ne);
if (ocr->beam() && !ocr->beam()->empty() && ocr->beam()->elements().front() == ocr) {
Beam* nb = ocr->beam()->clone();
nb->clear();
nb->setTrack(track);
nb->setScore(score);
nb->add(ncr);
ncr->setBeam(nb);
}
Tuplet* ot = ocr->tuplet();
if (ot)
cloneTuplets(ocr, ncr, ot, tupletMap, m, track);
if (oe->type() == Element::Type::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 = static_cast<Tie*>(on->tieFor()->linkedClone());
tie->setScore(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("cloneStaves: cannot find tie");
}
}
// add back spanners (going back from end to start spanner element
// makes sure the 'other' spanner anchor element is already set up)
// 'on' is the old spanner end note and 'nn' is the new spanner end note
for (Spanner* oldSp : on->spannerBack()) {
Note* newStart = Spanner::startElementFromSpanner(oldSp, nn);
if (newStart != nullptr) {
Spanner* newSp = static_cast<Spanner*>(oldSp->linkedClone());
newSp->setNoteSpan(newStart, nn);
score->addElement(newSp);
}
else {
qDebug("cloneStaves: cannot find spanner start note");
}
}
}
// two note tremolo
if (och->tremolo() && och->tremolo()->twoNotes()) {
if (och == och->tremolo()->chord1()) {
if (tremolo)
qDebug("unconnected two note tremolo");
tremolo = static_cast<Tremolo*>(och->tremolo()->linkedClone());
tremolo->setScore(nch->score());
tremolo->setParent(nch);
tremolo->setTrack(nch->track());
tremolo->setChords(nch, 0);
nch->setTremolo(tremolo);
}
else if (och == och->tremolo()->chord2()) {
if (!tremolo)
qDebug("first note for two note tremolo missing");
else {
tremolo->setChords(tremolo->chord1(), nch);
nch->setTremolo(tremolo);
}
}
else
qDebug("inconsistent two note tremolo");
}
}
}
if (!ns)
ns = nm->getSegment(oseg->segmentType(), oseg->tick());
ns->add(ne);
}
Segment* tst = nm->segments().firstCRSegment();
if (srcTrack % VOICES && !(track % VOICES) && (!tst || (!tst->element(track)))) {
Rest* rest = new Rest(score);
rest->setDuration(nm->len());
rest->setDurationType(nm->len().ticks());
rest->setTrack(track);
Segment* segment = nm->getSegment(rest, nm->tick());
segment->add(rest);
}
}
if (oe == 0)
continue;
Element* ne;
if (oe->generated())
continue;
else
ne = oe->linkedClone();
ne->setTrack(track);
ne->scanElements(score, localSetScore); //necessary?
ne->setScore(score);
if (oe->type() == Element::Type::BAR_LINE && adjustedBarlineSpan) {
BarLine* nbl = static_cast<BarLine*>(ne);
nbl->setSpan(adjustedBarlineSpan);
}
else if (oe->isChordRest()) {
ChordRest* ocr = static_cast<ChordRest*>(oe);
ChordRest* ncr = static_cast<ChordRest*>(ne);
if (ocr->beam() && !ocr->beam()->empty() && ocr->beam()->elements().front() == ocr) {
Beam* nb = ocr->beam()->clone();
nb->clear();
nb->setTrack(track);
nb->setScore(score);
nb->add(ncr);
ncr->setBeam(nb);
}
Tuplet* ot = ocr->tuplet();
if (ot)
cloneTuplets(ocr, ncr, ot, tupletMap, m, track);
if (oe->type() == Element::Type::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 = static_cast<Tie*>(on->tieFor()->linkedClone());
tie->setScore(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("cloneStaves: cannot find tie");
}
}
// add back spanners (going back from end to start spanner element
// makes sure the 'other' spanner anchor element is already set up)
// 'on' is the old spanner end note and 'nn' is the new spanner end note
for (Spanner* oldSp : on->spannerBack()) {
Note* newStart = Spanner::startElementFromSpanner(oldSp, nn);
if (newStart != nullptr) {
Spanner* newSp = static_cast<Spanner*>(oldSp->linkedClone());
newSp->setNoteSpan(newStart, nn);
score->addElement(newSp);
}
else {
qDebug("cloneStaves: cannot find spanner start note");
}
}
}
// two note tremolo
if (och->tremolo() && och->tremolo()->twoNotes()) {
if (och == och->tremolo()->chord1()) {
if (tremolo)
qDebug("unconnected two note tremolo");
tremolo = static_cast<Tremolo*>(och->tremolo()->linkedClone());
tremolo->setScore(nch->score());
tremolo->setParent(nch);
tremolo->setTrack(nch->track());
tremolo->setChords(nch, 0);
nch->setTremolo(tremolo);
}
else if (och == och->tremolo()->chord2()) {
if (!tremolo)
qDebug("first note for two note tremolo missing");
else {
tremolo->setChords(tremolo->chord1(), nch);
nch->setTremolo(tremolo);
}
}
else
qDebug("inconsistent two note tremolo");
}
}
}
if (!ns)
ns = nm->getSegment(oseg->segmentType(), oseg->tick());
ns->add(ne);
}
}
}
@ -625,7 +657,7 @@ void cloneStaves(Score* oscore, Score* score, const QList<int>& map)
int track = -1;
if (e->track() != -1) {
// try to map track
track = mapTrack(e->track(), map);
track = trackList.value(e->track(), -1);
if (track == -1) {
// even if track not in excerpt, we need to clone system elements
if (e->systemFlag())
@ -656,7 +688,7 @@ void cloneStaves(Score* oscore, Score* score, const QList<int>& map)
for (int dstStaffIdx = 0; dstStaffIdx < n; ++dstStaffIdx) {
Staff* srcStaff = oscore->staff(map[dstStaffIdx]);
Staff* dstStaff = score->staff(dstStaffIdx);
// *dstStaff->clefList() = *srcStaff->clefList();
if (srcStaff->primaryStaff()) {
int span = srcStaff->barLineSpan();
int sIdx = srcStaff->idx();
@ -690,28 +722,45 @@ void cloneStaves(Score* oscore, Score* score, const QList<int>& map)
for (auto i : oscore->spanner()) {
Spanner* s = i.second;
int staffIdx = s->staffIdx();
int dstTrack = -1;
int dstTrack2 = -1;
int st = 0;
if (s->type() == Element::Type::VOLTA) {
//always export voltas to first staff in part
dstTrack = s->voice();
dstTrack = 0;
dstTrack2 = 0;
cloneSpanner(s, score, dstTrack, dstTrack2);
}
else { //export other spanner if staffidx matches
for (int index : map) {
if (index == staffIdx) {
dstTrack = st * VOICES + s->voice();
dstTrack2 = st * VOICES + (s->track2() % VOICES);
break;
}
++st;
else if (s->isHairpin()) {
//always export these spanners to first voice of the destination staff
QList<int> track1;
for (int i = s->track(); i < s->track() + VOICES; i++) {
track1 += trackList.values(i);
}
for (int track : track1) {
if (!(track % VOICES))
cloneSpanner(s, score, track, track);
}
}
else {
if (trackList.value(s->track(), -1) == -1 || trackList.value(s->track2(), -1) == -1)
continue;
QList<int> track1 = trackList.values(s->track());
QList<int> track2 = trackList.values(s->track2());
if (track1.length() != track2.length())
continue;
//export other spanner if staffidx matches
for (int i = 0; i < track1.length(); i++) {
dstTrack = track1.at(i);
dstTrack2 = track2.at(i);
cloneSpanner(s, score, dstTrack, dstTrack2);
}
}
if (dstTrack == -1)
continue;
cloneSpanner(s, score, dstTrack, dstTrack2);
}
}
@ -902,6 +951,15 @@ void cloneStaff2(Staff* srcStaff, Staff* dstStaff, int stick, int etick)
{
Score* oscore = srcStaff->score();
Score* score = dstStaff->score();
Excerpt* oex = oscore->excerpt();
Excerpt* ex = score->excerpt();
QMultiMap<int, int> otracks, tracks;
if (oex)
otracks = oex->tracks();
if (ex)
tracks = ex->tracks();
Measure* m1 = oscore->tick2measure(stick);
Measure* m2 = oscore->tick2measure(etick);
@ -913,13 +971,43 @@ void cloneStaff2(Staff* srcStaff, Staff* dstStaff, int stick, int etick)
int srcStaffIdx = oscore->staffIdx(srcStaff);
int dstStaffIdx = score->staffIdx(dstStaff);
int sTrack = srcStaffIdx * VOICES;
int eTrack = sTrack + VOICES;
QMap<int, int> map;
for (int i = sTrack; i < eTrack; i++) {
if (!oex && !ex)
map.insert(i, dstStaffIdx * VOICES + i % VOICES);
else if (oex && !ex) {
if (otracks.key(i, -1) != -1)
map.insert(i, otracks.key(i));
}
else if (!oex && ex) {
for (int j : tracks.values(i)) {
if (dstStaffIdx * VOICES <= j && j < (dstStaffIdx + 1) * VOICES) {
map.insert(i, j);
break;
}
}
}
else if (oex && ex) {
if (otracks.key(i, -1) != -1) {
for (int j : tracks.values(otracks.key(i))) {
if (dstStaffIdx * VOICES <= j && j < (dstStaffIdx + 1) * VOICES) {
map.insert(i, j);
break;
}
}
}
}
}
for (Measure* m = m1; m && (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) {
for (int srcTrack : map.keys()) {
TupletMap tupletMap; // tuplets cannot cross measure boundaries
int dstTrack = dstStaffIdx * VOICES + (srcTrack - sTrack);
int dstTrack = map.value(srcTrack);
for (Segment* oseg = m->first(); oseg; oseg = oseg->next()) {
Element* oe = oseg->element(srcTrack);
if (oe == 0 || oe->generated())
@ -1037,6 +1125,9 @@ QList<Excerpt*> Excerpt::createAllExcerpt(MasterScore *score)
if (part->show()) {
Excerpt* e = new Excerpt(score);
e->parts().append(part);
for (int i = part->startTrack(), j = 0; i < part->endTrack(); i++, j++) {
e->tracks().insert(i, j);
}
QString name = createName(part->partName(), all);
e->setTitle(name);
all.append(e);

View file

@ -18,6 +18,7 @@ namespace Ms {
class MasterScore;
class Score;
class Part;
class Measure;
class Xml;
class Staff;
class XmlReader;
@ -28,6 +29,8 @@ class XmlReader;
// @P title string the title of this part
//---------------------------------------------------------
#include <QMultiMap>
class Excerpt : public QObject {
Q_OBJECT
Q_PROPERTY(Ms::Score* partScore READ partScore)
@ -37,14 +40,18 @@ class Excerpt : public QObject {
Score* _partScore { 0 };
QString _title;
QList<Part*> _parts;
QMultiMap<int, int> _tracks;
public:
Excerpt(MasterScore* s = 0) { _oscore = s; }
Excerpt(MasterScore* s = 0) { _oscore = s; }
QList<Part*>& parts() { return _parts; }
void setParts(const QList<Part*>& p) { _parts = p; }
MasterScore* oscore() const { return _oscore; }
QMultiMap<int, int>& tracks() { return _tracks; }
void setTracks(const QMultiMap<int, int> t) { _tracks = t; }
void setPartScore(Score* s) { _partScore = s; }
Score* partScore() const { return _partScore; }
@ -62,7 +69,7 @@ class Excerpt : public QObject {
extern void createExcerpt(Excerpt*);
extern void deleteExcerpt(Excerpt*);
extern void cloneStaves(Score* oscore, Score* score, const QList<int>& map);
extern void cloneStaves(Score* oscore, Score* score, const QList<int>& map, QMultiMap<int, int>& allTracks);
extern void cloneStaff(Staff* ostaff, Staff* nstaff);
extern void cloneStaff2(Staff* ostaff, Staff* nstaff, int stick, int etick);

View file

@ -1953,6 +1953,9 @@ void Score::respace(std::vector<ChordRest*>* elements)
qreal Score::computeMinWidth(Segment* s, bool isFirstMeasureInSystem)
{
if (!s)
return 0.0;
qreal x;
Shape ls;
@ -3902,6 +3905,7 @@ void Score::doLayoutRange(int stick, int etick)
//---------------------------------------------------
Measure* m = tick2measure(stick);
// start layout one measure earlier to handle clefs and cautionary elements
if (m->prevMeasureMM()) {
m = m->prevMeasureMM();

View file

@ -2130,7 +2130,15 @@ void Measure::read(XmlReader& e, int staffIdx)
void Measure::checkMeasure(int staffIdx)
{
for (int track = staffIdx * VOICES + 1; track % VOICES && hasVoice(track); track++) {
score()->staff(staffIdx)->setExcerpt(score()->excerpt());
int n = VOICES;
if (score()->staff(staffIdx)->excerpt())
n = 1;
if (isMMRest())
return;
for (int track = staffIdx * VOICES; (n || track % n) && hasVoice(track); track++) {
Segment* seg = first();
if (!seg->element(track))
seg = seg->nextCR(track, false);
@ -2142,19 +2150,19 @@ void Measure::checkMeasure(int staffIdx)
int ticks = seg->tick() - stick;
while (seg) {
if (ticks) {
if (ticks > 1) {
Fraction f = Fraction::fromTicks(ticks);
Rest* rest = new Rest(score());
rest->setDuration(f);
rest->setTrack(track);
Segment* segment = getSegment(rest, stick);
segment->add(rest);
rest->setGap(true);
seg = segment;
score()->undoAddCR(rest, this, stick);
}
pseg = seg;
if (!seg->element(track)->isChordRest())
break;
stick = seg->tick() + toChordRest(seg->element(track))->actualTicks();
for (Segment* s = seg->nextCR(track, true); s; s = s->nextCR(track, true)) {
if (!s->element(track))
@ -2668,12 +2676,10 @@ void Measure::sortStaves(QList<int>& dst)
// exchangeVoice
//---------------------------------------------------------
void Measure::exchangeVoice(int v1, int v2, int staffIdx)
void Measure::exchangeVoice(int strack, int dtrack, int staffIdx)
{
int strack = staffIdx * VOICES + v1;
int dtrack = staffIdx * VOICES + v2;
for (Segment* s = first(Segment::Type::ChordRest); s; s = s->next(Segment::Type::ChordRest)) {
for (Segment* s = first(Segment::Type::ChordRest); s; s = s->next(Segment::Type::ChordRest)) {
s->swapElements(strack, dtrack);
}
@ -2750,6 +2756,8 @@ void Measure::checkMultiVoices(int staffIdx)
bool Measure::hasVoice(int track) const
{
if (track >= int(mstaves().size() * VOICES))
return false;
for (Segment* s = first(); s; s = s->next()) {
if (s->segmentType() != Segment::Type::ChordRest)
continue;

View file

@ -23,6 +23,7 @@
#include "noteevent.h"
#include "pitchspelling.h"
#include "shape.h"
#include "tremolo.h"
class QPainter;

View file

@ -1774,11 +1774,12 @@ void Score::setMetaTag(const QString& tag, const QString& val)
// addExcerpt
//---------------------------------------------------------
void MasterScore::addExcerpt(Score* score)
void MasterScore::addExcerpt(Score* score, QMultiMap<int, int>& tracks, Excerpt* ex)
{
Excerpt* ex = new Excerpt(this);
ex->setPartScore(score);
if (!ex)
ex = new Excerpt(this);
excerpts().append(ex);
ex->setPartScore(score);
ex->setTitle(score->fileInfo()->completeBaseName());
for (Staff* s : score->staves()) {
LinkedStaves* ls = s->linkedStaves();
@ -1791,6 +1792,24 @@ void MasterScore::addExcerpt(Score* score)
}
}
}
if (tracks.isEmpty()) {
for (Staff* s : score->staves()) {
LinkedStaves* ls = s->linkedStaves();
if (ls == 0)
continue;
for (Staff* ps : ls->staves()) {
if (ps->primaryStaff()) {
for (int i = 0; i < VOICES; i++)
tracks.insert(ps->idx() * VOICES + i % VOICES, s->idx() * VOICES + i % VOICES);
break;
}
}
}
ex->setTracks(tracks);
}
else
ex->setTracks(tracks);
setExcerptsChanged(true);
}
@ -3975,6 +3994,9 @@ void Score::changeVoice(int voice)
ChordRest* dstCR = toChordRest(s->element(dstTrack));
Chord* dstChord = nullptr;
if (excerpt() && excerpt()->tracks().key(dstTrack, -1) == -1)
break;
// set up destination chord
if (dstCR && dstCR->type() == Element::Type::CHORD && dstCR->globalDuration() == chord->globalDuration()) {

View file

@ -27,6 +27,7 @@
#include "ottava.h"
#include "spannermap.h"
#include "rehearsalmark.h"
#include "tremolo.h"
class QPainter;
@ -369,6 +370,8 @@ class Score : public QObject, public ScoreElement {
int _linkId { 0 };
MasterScore* _masterScore;
QList<MuseScoreView*> viewer;
Excerpt* _excerpt = 0;
QString _mscoreVersion;
int _mscoreRevision;
@ -545,6 +548,9 @@ class Score : public QObject, public ScoreElement {
void readStaff(XmlReader&);
bool read(XmlReader&);
Excerpt* excerpt() { return _excerpt; }
void setExcerpt(Excerpt* e) { _excerpt = e; }
void cmdRemovePart(Part*);
void cmdAddTie();
void cmdAddHairpin(bool);
@ -661,6 +667,8 @@ class Score : public QObject, public ScoreElement {
void putNote(const Position&, bool replace, bool insert);
void putNoteInsert(const Position&);
void cloneVoice(int strack, int dtrack, Segment* sf, int lTick, bool link = true, bool spanner = true);
void repitchNote(const Position& pos, bool replace);
void regroupNotesAndRests(int startTick, int endTick, int track);
void cmdAddPitch(int pitch, bool addFlag, bool insert);
@ -1213,7 +1221,7 @@ class MasterScore : public Score {
void updateChannel();
void setSoloMute();
void addExcerpt(Score*);
void addExcerpt(Score* score, QMultiMap<int, int>& tracks, Excerpt* ex = 0);
void removeExcerpt(Score*);
};

View file

@ -104,6 +104,18 @@ void Score::write(Xml& xml, bool selectionOnly)
}
xml.stag("Score");
if (excerpt()) {
Excerpt* e = excerpt();
QMultiMap<int, int> trackList = e->tracks();
QMapIterator<int, int> i(trackList);
if (!(trackList.size() == e->parts().size() * VOICES) && !trackList.isEmpty()) {
while (i.hasNext()) {
i.next();
xml.tag(QString("Tracklist sTrack=\"%1\" dstTrack=\"%2\"").arg(i.key()).arg(i.value()), "");
}
}
}
switch (_layoutMode) {
case LayoutMode::PAGE:
case LayoutMode::FLOAT:
@ -237,7 +249,7 @@ void Score::write(Xml& xml, bool selectionOnly)
}
//---------------------------------------------------------
// readStaff
// Staff
//---------------------------------------------------------
void Score::readStaff(XmlReader& e)
@ -1054,13 +1066,32 @@ bool Score::read(XmlReader& e)
// _beams.append(beam);
}
else if (tag == "Score") { // recursion
if (MScore::noExcerpts)
if (MScore::noExcerpts)
e.skipCurrentElement();
else {
QMultiMap<int, int> tracks;
while (e.readNextStartElement()) {
if (e.name() == "Tracklist") {
int strack = e.intAttribute("sTrack", -1);
int dtrack = e.intAttribute("dstTrack", -1);
if (strack == -1 || dtrack == -1)
continue;
tracks.insert(strack, dtrack);
e.readNext();
}
else {
e.unknown();
break;
}
}
MasterScore* m = masterScore();
Score* s = new Score(m, MScore::baseStyle());
Excerpt* ex = new Excerpt(m);
s->setExcerpt(ex);
ex->setPartScore(s);
s->read(e);
m->addExcerpt(s);
m->addExcerpt(s, tracks, ex);
}
}
else if (tag == "PageList") {

View file

@ -524,7 +524,8 @@ void Segment::add(Element* el)
}
else
v = el->visible();
if (v)
if (v && int(measure()->mstaves().size() * VOICES) > track)
measure()->mstaff(track / VOICES)->hasVoices = true;
}

View file

@ -26,6 +26,7 @@
#include "stafftype.h"
#include "groups.h"
#include "scoreElement.h"
#include "excerpt.h"
namespace Ms {
@ -100,6 +101,7 @@ class Staff : public QObject, public ScoreElement {
private:
Part* _part { 0 };
Excerpt* _excerpt { 0 };
ClefList clefs;
ClefTypeList _defaultClefType;
@ -150,6 +152,9 @@ class Staff : public QObject, public ScoreElement {
Part* part() const { return _part; }
void setPart(Part* p) { _part = p; }
Excerpt* excerpt() const { return _excerpt; }
void setExcerpt(Excerpt* e) { _excerpt = e; }
BracketType bracket(int idx) const;
int bracketSpan(int idx) const;
void setBracket(int idx, BracketType val);

File diff suppressed because it is too large Load diff

View file

@ -434,12 +434,32 @@ class ExchangeVoice : public UndoCommand {
int staff;
public:
ExchangeVoice(Measure*, int val1, int val2, int staff);
ExchangeVoice(Measure* ,int val1, int val2, int staff);
virtual void undo();
virtual void redo();
UNDO_NAME("ExchangeVoice")
};
//---------------------------------------------------------
// CloneVoice
//---------------------------------------------------------
class CloneVoice : public UndoCommand {
Segment* sf;
int lTick;
Segment* d; //Destination
int strack, dtrack;
int otrack;
bool linked;
bool first = true; //first redo
public:
CloneVoice(Segment* sf, int lTick, Segment* d, int strack, int dtrack, int otrack, bool linked = true);
virtual void undo();
virtual void redo();
UNDO_NAME("CloneVoice")
};
//---------------------------------------------------------
// ChangeInstrumentShort
//---------------------------------------------------------
@ -824,9 +844,10 @@ class ChangeImage : public UndoCommand {
class AddExcerpt : public UndoCommand {
Score* score;
QMultiMap<int, int> tracks;
public:
AddExcerpt(Score* s) : score(s) {}
AddExcerpt(Score* s, QMultiMap<int, int>& t) : score(s), tracks(t) {}
virtual void undo();
virtual void redo();
UNDO_NAME("AddExcerpt")
@ -838,9 +859,10 @@ class AddExcerpt : public UndoCommand {
class RemoveExcerpt : public UndoCommand {
Score* score;
QMultiMap<int, int> tracks;
public:
RemoveExcerpt(Score* s) : score(s) {}
RemoveExcerpt(Score* s, QMultiMap<int, int>& t) : score(s), tracks(t) {}
virtual void undo();
virtual void redo();
UNDO_NAME("RemoveExcerpt")

View file

@ -43,13 +43,37 @@ ExcerptItem::ExcerptItem(Excerpt* e, QListWidget* parent)
// PartItem
//---------------------------------------------------------
PartItem::PartItem(Part* p, QListWidget* parent)
PartItem::PartItem(Part* p, QTreeWidget* parent)
: QTreeWidgetItem(parent)
{
setFlags(Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable));
_part = p;
setText(0, p->partName().replace("/", "_"));
}
//---------------------------------------------------------
// InstrumentItem
//---------------------------------------------------------
InstrumentItem::InstrumentItem(PartItem* p, QListWidget* parent)
: QListWidgetItem(parent)
{
setFlags(Qt::ItemFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable));
setCheckState(Qt::Unchecked);
_part = p;
setText(p->partName().replace("/", "_"));
setFlags(Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable));
_partItem = p;
setText(p->part()->partName().replace("/", "_"));
}
//---------------------------------------------------------
// StaffItem
//---------------------------------------------------------
StaffItem::StaffItem(PartItem* li)
: QTreeWidgetItem(li)
{
setFlags(Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable));
for (int i = 1; i <= VOICES; i++) {
setCheckState(i, Qt::Checked);
}
}
//---------------------------------------------------------
@ -70,9 +94,11 @@ ExcerptsDialog::ExcerptsDialog(MasterScore* s, QWidget* parent)
ExcerptItem* ei = new ExcerptItem(e);
excerptList->addItem(ei);
}
QMultiMap<int, int> t;
for (Part* p : score->parts()) {
PartItem* item = new PartItem(p);
partList->addItem(item);
PartItem* pI = new PartItem(p);
InstrumentItem* item = new InstrumentItem(pI);
instrumentList->addItem(item);
}
connect(newButton, SIGNAL(clicked()), SLOT(newClicked()));
@ -80,20 +106,28 @@ ExcerptsDialog::ExcerptsDialog(MasterScore* s, QWidget* parent)
connect(deleteButton, SIGNAL(clicked()), SLOT(deleteClicked()));
connect(moveUpButton, SIGNAL(clicked()), SLOT(moveUpClicked()));
connect(moveDownButton, SIGNAL(clicked()), SLOT(moveDownClicked()));
connect(addButton, SIGNAL(clicked()), SLOT(addButtonClicked()));
connect(removeButton, SIGNAL(clicked()), SLOT(removeButtonClicked()));
connect(excerptList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
SLOT(excerptChanged(QListWidgetItem*, QListWidgetItem*)));
connect(partList, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
SLOT(partDoubleClicked(QListWidgetItem*)));
connect(partList, SIGNAL(itemClicked(QListWidgetItem*)), SLOT(partClicked(QListWidgetItem*)));
connect(partList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
SLOT(partDoubleClicked(QTreeWidgetItem*, int)));
connect(partList, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SLOT(partClicked(QTreeWidgetItem*,int)));
connect(instrumentList, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
SLOT(addButtonClicked()));
connect(title, SIGNAL(textChanged(const QString&)), SLOT(titleChanged(const QString&)));
for (int i = 1; i <= VOICES; i++)
partList->resizeColumnToContents(i);
int n = score->excerpts().size();
if (n > 0)
excerptList->setCurrentRow(0);
moveDownButton->setEnabled(n > 1);
moveUpButton->setEnabled(false);
bool flag = excerptList->currentItem() != 0;
editGroup->setEnabled(flag);
deleteButton->setEnabled(flag);
}
@ -113,35 +147,6 @@ void MuseScore::startExcerptsDialog()
cs->update();
}
//---------------------------------------------------------
// deleteClicked
//---------------------------------------------------------
void ExcerptsDialog::deleteClicked()
{
QListWidgetItem* cur = excerptList->currentItem();
if (cur == 0)
return;
delete cur;
//excerptList->takeItem(row);
}
//---------------------------------------------------------
// createName
//---------------------------------------------------------
QString ExcerptsDialog::createName(const QString& partName)
{
int count = excerptList->count();
QList<Excerpt*> excerpts;
for (int i = 0; i < count; ++i) {
Excerpt* ee = static_cast<ExcerptItem*>(excerptList->item(i))->excerpt();
excerpts.append(ee);
}
return Excerpt::createName(partName, excerpts);
}
//---------------------------------------------------------
// newClicked
//---------------------------------------------------------
@ -175,6 +180,20 @@ void ExcerptsDialog::newAllClicked()
}
}
//---------------------------------------------------------
// deleteClicked
//---------------------------------------------------------
void ExcerptsDialog::deleteClicked()
{
QListWidgetItem* cur = excerptList->currentItem();
if (cur == 0)
return;
delete cur;
//excerptList->takeItem(row);
}
//---------------------------------------------------------
// moveUpClicked
//---------------------------------------------------------
@ -210,6 +229,61 @@ void ExcerptsDialog::moveDownClicked()
excerptList->setCurrentRow(currentRow + 1);
}
//---------------------------------------------------------
// addButtonClicked
// add instrument to excerpt
//---------------------------------------------------------
void ExcerptsDialog::addButtonClicked()
{
if (!excerptList->currentItem() || !partList->isEnabled())
return;
Excerpt* cur = ((ExcerptItem*)(excerptList->currentItem()))->excerpt();
foreach(QListWidgetItem* i, instrumentList->selectedItems()) {
InstrumentItem* item = static_cast<InstrumentItem*>(i);
const PartItem* it = item->partItem();
if (it == 0)
continue;
PartItem* pi = new PartItem(it->part(), 0);
pi->setText(0, pi->part()->name());
cur->parts().append(pi->part());
partList->addTopLevelItem(pi);
for (Staff* s : *pi->part()->staves()) {
StaffItem* sli = new StaffItem(pi);
sli->setStaff(s);
for (int i = 0; i < VOICES; i++)
sli->setCheckState(i + 1, Qt::Checked);
}
pi->setText(0, pi->part()->partName());
}
cur->setTracks(mapTracks());
partList->resizeColumnToContents(0);
}
//---------------------------------------------------------
// removeButtonClicked
// remove instrument from score
//---------------------------------------------------------
void ExcerptsDialog::removeButtonClicked()
{
QList<QTreeWidgetItem*> wi = partList->selectedItems();
if (wi.isEmpty())
return;
Excerpt* cur = ((ExcerptItem*)(excerptList->currentItem()))->excerpt();
QTreeWidgetItem* item = wi.first();
cur->parts().removeAt(partList->indexOfTopLevelItem(item));
delete item;
cur->setTracks(mapTracks());
partList->resizeColumnToContents(0);
}
//---------------------------------------------------------
// excerptChanged
//---------------------------------------------------------
@ -220,35 +294,40 @@ void ExcerptsDialog::excerptChanged(QListWidgetItem* cur, QListWidgetItem*)
if (cur) {
Excerpt* e = ((ExcerptItem*)cur)->excerpt();
title->setText(e->title());
b = e->partScore() == 0;
// set selection:
QList<Part*>& pl = e->parts();
int n = partList->count();
for (int i = 0; i < n; ++i) {
PartItem* pi = (PartItem*)partList->item(i);
int idx = pl.indexOf(pi->part());
pi->setCheckState(idx != -1 ? Qt::Checked : Qt::Unchecked);
QMultiMap<int, int> tracks = e->tracks();
partList->clear();
for (Part* p: pl) {
PartItem* pi = new PartItem(p, partList);
partList->addTopLevelItem(pi);
for (Staff* s : *p->staves()) {
StaffItem* sli = new StaffItem(pi);
sli->setStaff(s);
sli->setDisabled(!b);
}
pi->setText(0, p->partName());
partList->setItemExpanded(pi, false);
}
b = e->partScore() == 0;
assignTracks(tracks);
}
else {
title->setText("");
int n = partList->count();
for (int i = 0; i < n; ++i) {
PartItem* pi = (PartItem*)partList->item(i);
pi->setCheckState(Qt::Unchecked);
}
partList->clear();
b = false;
}
partList->setEnabled(b);
instrumentList->setEnabled(b);
title->setEnabled(b);
addButton->setEnabled(b);
removeButton->setEnabled(b);
bool flag = excerptList->currentItem() != 0;
int n = excerptList->count();
int idx = excerptList->currentIndex().row();
moveUpButton->setEnabled(idx > 0);
moveDownButton->setEnabled(idx < (n-1));
editGroup->setEnabled(flag);
deleteButton->setEnabled(flag);
}
@ -256,8 +335,10 @@ void ExcerptsDialog::excerptChanged(QListWidgetItem* cur, QListWidgetItem*)
// partDoubleClicked
//---------------------------------------------------------
void ExcerptsDialog::partDoubleClicked(QListWidgetItem* item)
void ExcerptsDialog::partDoubleClicked(QTreeWidgetItem* item, int)
{
if (!title->isEnabled())
return;
PartItem* pi = (PartItem*)item;
title->setText(pi->part()->partName());
}
@ -266,58 +347,23 @@ void ExcerptsDialog::partDoubleClicked(QListWidgetItem* item)
// partClicked
//---------------------------------------------------------
void ExcerptsDialog::partClicked(QListWidgetItem* item)
void ExcerptsDialog::partClicked(QTreeWidgetItem*, int)
{
QListWidgetItem* cur = excerptList->currentItem();
if (cur == 0)
return;
Excerpt* excerpt = static_cast<ExcerptItem*>(cur)->excerpt();
PartItem* pi = static_cast<PartItem*>(item);
if (item->checkState() == Qt::Checked) {
excerpt->parts().clear();
for (int i = 0; i < partList->count(); i++) {
PartItem* pii = static_cast<PartItem*>(partList->item(i));
if (pii->checkState() == Qt::Checked)
excerpt->parts().append(pii->part());
}
}
else {
excerpt->parts().removeOne(pi->part());
}
Excerpt* excerpt = static_cast<ExcerptItem*>(cur)->excerpt();
excerpt->setTracks(mapTracks());
}
//---------------------------------------------------------
// createExcerpt
// doubleClickedInstrument
//---------------------------------------------------------
void ExcerptsDialog::createExcerptClicked(QListWidgetItem* cur)
void ExcerptsDialog::doubleClickedInstrument(QTreeWidgetItem*)
{
Excerpt* e = static_cast<ExcerptItem*>(cur)->excerpt();
if (e->partScore())
return;
if (e->parts().isEmpty())
return;
Score* nscore = new Score(e->oscore());
e->setPartScore(nscore);
nscore->setName(e->title()); // needed before AddExcerpt
qDebug() << " + Add part : " << e->title();
score->undo(new AddExcerpt(nscore));
createExcerpt(e);
// a new excerpt is created in AddExcerpt, make sure the parts are filed
for (Excerpt* ee : e->oscore()->excerpts()) {
if (ee->partScore() == nscore) {
ee->parts().clear();
ee->parts().append(e->parts());
}
}
partList->setEnabled(false);
title->setEnabled(false);
addButtonClicked();
}
//---------------------------------------------------------
@ -335,7 +381,74 @@ void ExcerptsDialog::titleChanged(const QString& s)
}
//---------------------------------------------------------
// titleChanged
// createName
//---------------------------------------------------------
QString ExcerptsDialog::createName(const QString& partName)
{
int count = excerptList->count();
QList<Excerpt*> excerpts;
for (int i = 0; i < count; ++i) {
Excerpt* ee = static_cast<ExcerptItem*>(excerptList->item(i))->excerpt();
excerpts.append(ee);
}
return Excerpt::createName(partName, excerpts);
}
//---------------------------------------------------------
// mapTracks
//---------------------------------------------------------
QMultiMap<int, int> ExcerptsDialog::mapTracks() {
QMultiMap<int, int> tracks;
int track = 0;
for (QTreeWidgetItem* pwi = partList->itemAt(0,0); pwi; pwi = partList->itemBelow(pwi)) {
PartItem* pi = (PartItem*)pwi;
Part* p = pi->part();
for (int j = 0; j < pwi->childCount(); j++) {
for (int k = 0; k < VOICES; k++) {
if (pwi->child(j)->checkState(k+1) == Qt::Checked) {
int voiceOff = 0;
int srcTrack = p->startTrack() + j * VOICES + k;
for (int i = srcTrack & ~3; i < srcTrack; i++) {
QList<int> t = tracks.values(i);
for (int ti : t) {
if (ti >= (track & ~3))
voiceOff++;
}
}
tracks.insert(srcTrack, (track & ~3) + voiceOff);
}
track++;
}
}
}
return tracks;
}
//---------------------------------------------------------
// assignTracks
//---------------------------------------------------------
void ExcerptsDialog::assignTracks(QMultiMap<int, int> tracks) {
int track = 0;
for (QTreeWidgetItem* pwi = partList->itemAt(0,0); pwi; pwi = partList->itemBelow(pwi)) {
for (int j = 0; j < pwi->childCount(); j++) {
for (int h = 0; h < VOICES; h++)
pwi->child(j)->setCheckState(h + 1, Qt::Unchecked);
for (int k = 0; k < VOICES; k++) {
int checkTrack = tracks.key(track, -1);
if (checkTrack != -1)
pwi->child(j)->setCheckState((checkTrack % VOICES)+ 1, Qt::Checked);
track++;
}
}
}
}
//---------------------------------------------------------
// isInPartList
//---------------------------------------------------------
bool ExcerptsDialog::isInPartsList(Excerpt* e)
@ -353,6 +466,40 @@ bool ExcerptsDialog::isInPartsList(Excerpt* e)
return false;
}
//---------------------------------------------------------
// createExcerpt
//---------------------------------------------------------
void ExcerptsDialog::createExcerptClicked(QListWidgetItem* cur)
{
Excerpt* e = static_cast<ExcerptItem*>(cur)->excerpt();
if (e->partScore())
return;
if (e->parts().isEmpty())
return;
Score* nscore = new Score(e->oscore());
nscore->setExcerpt(e);
e->setPartScore(nscore);
nscore->setName(e->title()); // needed before AddExcerpt
qDebug() << " + Add part : " << e->title();
score->undo(new AddExcerpt(nscore, e->tracks()));
createExcerpt(e);
// a new excerpt is created in AddExcerpt, make sure the parts are filed
for (Excerpt* ee : e->oscore()->excerpts()) {
if (ee->partScore() == nscore) {
ee->parts().clear();
ee->parts().append(e->parts());
}
}
partList->setEnabled(false);
title->setEnabled(false);
}
//---------------------------------------------------------
// accept
//---------------------------------------------------------
@ -375,7 +522,7 @@ void ExcerptsDialog::accept()
deleteExcerpt(e);
// remove the excerpt
score->undo(new RemoveExcerpt(partScore));
score->undo(new RemoveExcerpt(partScore, e->tracks()));
}
}
else
@ -394,6 +541,7 @@ void ExcerptsDialog::accept()
}
// Third pass : Remove empty parts.
qDebug() << "\nThird pass : remove empty parts";
int i = 0;
while (i < excerptList->count()) {
// This new part is empty, so we don't create an excerpt but remove it from the list.
@ -441,4 +589,3 @@ void ExcerptsDialog::accept()
QDialog::accept();
}
}

View file

@ -28,6 +28,7 @@ namespace Ms {
class MasterScore;
class Excerpt;
class Part;
class Staff;
//---------------------------------------------------------
// ExcerptItem
@ -45,12 +46,39 @@ class ExcerptItem : public QListWidgetItem {
// PartItem
//---------------------------------------------------------
class PartItem : public QListWidgetItem {
Part* _part;
class PartItem : public QTreeWidgetItem {
Part* _part;
public:
PartItem(Part*, QListWidget* parent = 0);
Part* part() const { return _part; }
PartItem(Part*, QTreeWidget* parent = 0);
Part* part() const { return _part; }
};
//---------------------------------------------------------
// PartiturPartsItem
//---------------------------------------------------------
class InstrumentItem : public QListWidgetItem {
PartItem* _partItem;
public:
InstrumentItem(PartItem*, QListWidget* parent = 0);
PartItem* partItem() const { return _partItem; }
};
//---------------------------------------------------------
// StaffListItem
//---------------------------------------------------------
class StaffItem : public QTreeWidgetItem {
Staff* _staff { 0 };
public:
StaffItem();
StaffItem(PartItem* li);
Staff* staff() const { return _staff; }
void setStaff(Staff* s) { _staff = s; }
};
//---------------------------------------------------------
@ -72,14 +100,22 @@ class ExcerptsDialog : public QDialog, private Ui::ExcerptsDialog {
void moveUpClicked();
void moveDownClicked();
void excerptChanged(QListWidgetItem* cur, QListWidgetItem* prev);
void partDoubleClicked(QListWidgetItem*);
void partClicked(QListWidgetItem*);
void partDoubleClicked(QTreeWidgetItem*, int);
void partClicked(QTreeWidgetItem*, int);
void createExcerptClicked(QListWidgetItem*);
void titleChanged(const QString&);
bool isInPartsList(Excerpt* e);
public:
ExcerptsDialog(MasterScore*, QWidget* parent = 0);
QMultiMap<int, int> mapTracks();
void assignTracks(QMultiMap<int, int> );
void doubleClickedInstrument(QTreeWidgetItem*);
void addButtonClicked();
void removeButtonClicked();
public:
ExcerptsDialog(MasterScore*, QWidget* parent = 0);
};

View file

@ -6,155 +6,359 @@
<rect>
<x>0</x>
<y>0</y>
<width>660</width>
<height>347</height>
<width>713</width>
<height>580</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>MuseScore: Parts</string>
</property>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Select Part</string>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QSplitter" name="splitte">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListWidget" name="excerptList">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QGroupBox" name="excerptGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Select Part</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<layout class="QVBoxLayout" name="move">
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="moveUpButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Move part up</string>
</property>
<property name="accessibleDescription">
<string>Move part up</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/arrow_up.svg</normaloff>:/data/icons/arrow_up.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="moveDownButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Move part down</string>
</property>
<property name="accessibleDescription">
<string>Move part down</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/arrow_down.svg</normaloff>:/data/icons/arrow_down.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="excerptList">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="buttons">
<item>
<widget class="QPushButton" name="newAllButton">
<property name="text">
<string>New All</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="newButton">
<property name="text">
<string>New</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deleteButton">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="editGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Edit Part</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QHBoxLayout" name="partTitle">
<item>
<widget class="QLabel" name="ExcerptTitle">
<property name="text">
<string>Part title:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="title"/>
</item>
</layout>
</item>
<item>
<widget class="QSplitter" name="instruments">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QGroupBox" name="scoreInst">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="uniformItemSizes">
<bool>true</bool>
<property name="title">
<string>Instruments in Score</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QListWidget" name="instrumentList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="accessibleName">
<string>Partitur List</string>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>26</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="addButton">
<property name="accessibleDescription">
<string>Add instrument</string>
</property>
<property name="text">
<string>+</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeButton">
<property name="accessibleDescription">
<string>Remove instrument</string>
</property>
<property name="text">
<string>-</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>26</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QToolButton" name="moveUpButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Move part up</string>
</property>
<property name="accessibleDescription">
<string>Move part up</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/arrow_up.svg</normaloff>:/data/icons/arrow_up.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="moveDownButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Move part down</string>
</property>
<property name="accessibleDescription">
<string>Move part down</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/arrow_down.svg</normaloff>:/data/icons/arrow_down.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout">
<item>
<widget class="QPushButton" name="deleteButton">
<property name="text">
<string>Delete</string>
<widget class="QGroupBox" name="partListGroup">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Instruments in Part</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTreeWidget" name="partList">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<column>
<property name="text">
<string>Instrument</string>
</property>
</column>
<column>
<property name="text">
<string>1</string>
</property>
</column>
<column>
<property name="text">
<string>2</string>
</property>
</column>
<column>
<property name="text">
<string>3</string>
</property>
</column>
<column>
<property name="text">
<string>4</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="newAllButton">
<property name="text">
<string>New All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="newButton">
<property name="text">
<string>New</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="0" column="5">
<widget class="QGroupBox" name="editGroup">
<property name="title">
<string>Edit Part</string>
</property>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Part title:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="title"/>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Instrument:</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QListWidget" name="partList"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="0" colspan="6">
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
@ -164,11 +368,7 @@
</layout>
</widget>
<tabstops>
<tabstop>title</tabstop>
<tabstop>partList</tabstop>
<tabstop>deleteButton</tabstop>
<tabstop>newAllButton</tabstop>
<tabstop>newButton</tabstop>
</tabstops>
<resources>
<include location="musescore.qrc"/>

View file

@ -757,6 +757,7 @@ void MuseScore::newFile()
xs->setName(x->title());
xs->style()->set(StyleIdx::createMultiMeasureRests, true);
x->setPartScore(xs);
xs->setExcerpt(x);
score->excerpts().append(x);
createExcerpt(x);
score->setExcerptsChanged(true);

View file

@ -2374,6 +2374,7 @@ Score::FileError importGTP(MasterScore* score, const QString& name)
// create parts (excerpts)
//
foreach(Part* part, score->parts()) {
QMultiMap<int, int> tracks;
Score* pscore = new Score(static_cast<MasterScore*>(score));
pscore->style()->set(StyleIdx::createMultiMeasureRests, true);
@ -2394,7 +2395,20 @@ Score::FileError importGTP(MasterScore* score, const QString& name)
p->staves()->append(s);
pscore->staves().append(s);
stavesMap.append(score->staffIdx(staff));
cloneStaves(score, pscore, stavesMap);
for (int i = score->staffIdx(staff) * VOICES, j = 0; i < score->staffIdx(staff) * VOICES + VOICES; i++, j++)
tracks.insert(i, j);
pscore->setName(part->partName());
Excerpt* excerpt = new Excerpt(score);
excerpt->setTracks(tracks);
excerpt->setPartScore(pscore);
pscore->setExcerpt(excerpt);
excerpt->setTitle(part->partName());
excerpt->parts().append(part);
score->excerpts().append(excerpt);
cloneStaves(score, pscore, stavesMap, tracks);
if (staff->part()->instrument()->stringData()->strings() > 0 && part->staves()->front()->staffType()->group() == StaffGroup::STANDARD) {
p->setStaves(2);
@ -2412,13 +2426,6 @@ Score::FileError importGTP(MasterScore* score, const QString& name)
}
pscore->appendPart(p);
pscore->setName(part->partName());
Excerpt* excerpt = new Excerpt(score);
excerpt->setPartScore(pscore);
excerpt->setTitle(part->partName());
excerpt->parts().append(part);
score->excerpts().append(excerpt);
//
// create excerpt title
//

View file

@ -478,13 +478,27 @@ void MuseScore::editInstrList()
if (masterScore->measures()->size() == 0)
masterScore->insertMeasure(Element::Type::MEASURE, 0, false);
QList<Score*> toDelete;
for (Excerpt* excpt : masterScore->excerpts()) {
if (excpt->partScore()->staves().size() == 0)
toDelete.append(excpt->partScore());
QList<Staff*> sl = excpt->partScore()->staves();
QMultiMap<int, int> tr = excpt->tracks();
if (sl.size() == 0)
masterScore->undo(new RemoveExcerpt(excpt->partScore(), excpt->tracks()));
else {
for (Staff* s : sl) {
LinkedStaves* sll = s->linkedStaves();
for (Staff* ss : sll->staves())
if (ss->primaryStaff()) {
for (int i = s->idx() * VOICES; i < (s->idx() + 1) * VOICES; i++) {
int strack = tr.key(i, -1);
if (strack != -1 && ((strack & ~3) == ss->idx()))
break;
else if (strack != -1)
tr.insert(ss->idx() + strack % VOICES, tr.value(strack, -1));
}
}
}
}
}
for(Score* s: toDelete)
masterScore->undo(new RemoveExcerpt(s));
masterScore->setLayoutAll();
masterScore->endCmd();

View file

@ -1495,9 +1495,8 @@ void MuseScore::updateInspector()
_inspector->setElement(cv->getEditObject());
else if (state() == STATE_FOTO)
_inspector->setElement(cv->fotoLasso());
else {
else
_inspector->setElements(cs->selection().elements());
}
}
else
_inspector->setElement(0);
@ -2508,10 +2507,11 @@ static bool doConvert(Score* cs, QString fn)
for (Excerpt* e : excerpts) {
Score* nscore = new Score(e->oscore());
e->setPartScore(nscore);
nscore->setExcerpt(e);
nscore->masterScore()->setName(e->title()); // needed before AddExcerpt
nscore->style()->set(StyleIdx::createMultiMeasureRests, true);
cs->startCmd();
cs->undo(new AddExcerpt(nscore));
cs->undo(new AddExcerpt(nscore, e->tracks()));
createExcerpt(e);
cs->endCmd();
}
@ -2533,10 +2533,11 @@ static bool doConvert(Score* cs, QString fn)
for (Excerpt* e: excerpts) {
Score* nscore = new Score(e->oscore());
e->setPartScore(nscore);
nscore->setExcerpt(e);
nscore->setName(e->title()); // needed before AddExcerpt
nscore->style()->set(StyleIdx::createMultiMeasureRests, true);
cs->startCmd();
cs->undo(new AddExcerpt(nscore));
cs->undo(new AddExcerpt(nscore, e->tracks()));
createExcerpt(e);
cs->endCmd();
}

View file

@ -409,8 +409,6 @@
<string>4</string>
</Note>
</Chord>
<move>3/4</move>
<endSpanner id="5"/>
</Measure>
<Measure number="2">
<Chord>
@ -424,7 +422,7 @@
<string>2</string>
</Note>
</Chord>
<HairPin id="6">
<HairPin id="5">
<subtype>1</subtype>
<lid>21</lid>
</HairPin>
@ -439,7 +437,7 @@
<string>3</string>
</Note>
</Chord>
<endSpanner id="6"/>
<endSpanner id="5"/>
<Chord>
<lid>17</lid>
<durationType>quarter</durationType>
@ -451,8 +449,6 @@
<string>4</string>
</Note>
</Chord>
<move>3/4</move>
<endSpanner id="7"/>
</Measure>
</Staff>
<Staff id="2">
@ -472,7 +468,7 @@
<string>2</string>
</Note>
</Chord>
<HairPin id="5">
<HairPin id="6">
<subtype>0</subtype>
<lid>20</lid>
</HairPin>
@ -487,6 +483,7 @@
<string>3</string>
</Note>
</Chord>
<endSpanner id="6"/>
<Chord>
<lid>10</lid>
<durationType>quarter</durationType>
@ -526,6 +523,7 @@
<string>3</string>
</Note>
</Chord>
<endSpanner id="7"/>
<Chord>
<lid>17</lid>
<durationType>quarter</durationType>

View file

@ -503,10 +503,6 @@
<name>segno</name>
<lid>102</lid>
</Symbol>
<Symbol>
<name>segno</name>
<lid>112</lid>
</Symbol>
<Rest>
<lid>103</lid>
<durationType>measure</durationType>
@ -533,10 +529,6 @@
<name>coda</name>
<lid>109</lid>
</Symbol>
<Symbol>
<name>coda</name>
<lid>113</lid>
</Symbol>
<Rest>
<lid>110</lid>
<durationType>measure</durationType>
@ -1136,10 +1128,6 @@
<name>segno</name>
<lid>102</lid>
</Symbol>
<Symbol>
<name>segno</name>
<lid>112</lid>
</Symbol>
<Rest>
<lid>103</lid>
<durationType>measure</durationType>
@ -1166,10 +1154,6 @@
<name>coda</name>
<lid>109</lid>
</Symbol>
<Symbol>
<name>coda</name>
<lid>113</lid>
</Symbol>
<Rest>
<lid>110</lid>
<durationType>measure</durationType>
@ -1551,7 +1535,6 @@
<Measure number="33">
<Symbol>
<name>segno</name>
<lid>112</lid>
</Symbol>
<Rest>
<lid>103</lid>
@ -1569,7 +1552,6 @@
<Measure number="35">
<Symbol>
<name>coda</name>
<lid>113</lid>
</Symbol>
<Rest>
<lid>110</lid>

View file

@ -140,11 +140,6 @@
<lid>6</lid>
<text><sym>metNoteQuarterUp</sym> = 120</text>
</Tempo>
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="-125" vibrato="0"/>
<point time="100" pitch="-250" vibrato="0"/>
</TremoloBar>
<Chord>
<lid>7</lid>
<durationType>quarter</durationType>
@ -170,11 +165,6 @@
</Rest>
</Measure>
<Measure number="2">
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="150" vibrato="0"/>
<point time="100" pitch="0" vibrato="0"/>
</TremoloBar>
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="150" vibrato="0"/>
@ -205,11 +195,6 @@
</Rest>
</Measure>
<Measure number="3">
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="-550" vibrato="0"/>
<point time="100" pitch="-550" vibrato="0"/>
</TremoloBar>
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="-550" vibrato="0"/>
@ -231,11 +216,6 @@
<point time="50" pitch="-550" vibrato="0"/>
<point time="100" pitch="-400" vibrato="0"/>
</TremoloBar>
<TremoloBar>
<point time="0" pitch="-550" vibrato="0"/>
<point time="50" pitch="-550" vibrato="0"/>
<point time="100" pitch="-400" vibrato="0"/>
</TremoloBar>
<Chord>
<lid>24</lid>
<durationType>quarter</durationType>
@ -257,11 +237,6 @@
</Rest>
</Measure>
<Measure number="4">
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="200" vibrato="0"/>
<point time="100" pitch="300" vibrato="0"/>
</TremoloBar>
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="200" vibrato="0"/>
@ -282,10 +257,6 @@
<point time="0" pitch="300" vibrato="0"/>
<point time="100" pitch="300" vibrato="0"/>
</TremoloBar>
<TremoloBar>
<point time="0" pitch="300" vibrato="0"/>
<point time="100" pitch="300" vibrato="0"/>
</TremoloBar>
<Chord>
<lid>33</lid>
<durationType>quarter</durationType>
@ -468,11 +439,6 @@
<lid>6</lid>
<text><sym>metNoteQuarterUp</sym> = 120</text>
</Tempo>
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="-125" vibrato="0"/>
<point time="100" pitch="-250" vibrato="0"/>
</TremoloBar>
<Chord>
<lid>7</lid>
<durationType>quarter</durationType>
@ -498,11 +464,6 @@
</Rest>
</Measure>
<Measure number="2">
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="150" vibrato="0"/>
<point time="100" pitch="0" vibrato="0"/>
</TremoloBar>
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="150" vibrato="0"/>
@ -533,11 +494,6 @@
</Rest>
</Measure>
<Measure number="3">
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="-550" vibrato="0"/>
<point time="100" pitch="-550" vibrato="0"/>
</TremoloBar>
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="-550" vibrato="0"/>
@ -559,11 +515,6 @@
<point time="50" pitch="-550" vibrato="0"/>
<point time="100" pitch="-400" vibrato="0"/>
</TremoloBar>
<TremoloBar>
<point time="0" pitch="-550" vibrato="0"/>
<point time="50" pitch="-550" vibrato="0"/>
<point time="100" pitch="-400" vibrato="0"/>
</TremoloBar>
<Chord>
<lid>24</lid>
<durationType>quarter</durationType>
@ -585,11 +536,6 @@
</Rest>
</Measure>
<Measure number="4">
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="200" vibrato="0"/>
<point time="100" pitch="300" vibrato="0"/>
</TremoloBar>
<TremoloBar>
<point time="0" pitch="0" vibrato="0"/>
<point time="50" pitch="200" vibrato="0"/>
@ -610,10 +556,6 @@
<point time="0" pitch="300" vibrato="0"/>
<point time="100" pitch="300" vibrato="0"/>
</TremoloBar>
<TremoloBar>
<point time="0" pitch="300" vibrato="0"/>
<point time="100" pitch="300" vibrato="0"/>
</TremoloBar>
<Chord>
<lid>33</lid>
<durationType>quarter</durationType>

View file

@ -137,18 +137,16 @@ void TestChordSymbol::testNoSystem()
//
QList<Part*> parts;
parts.append(score->parts().at(0));
Score* nscore = new Score(score);
score->Score::undo(new AddExcerpt(nscore));
{
Excerpt ex(score);
ex.setPartScore(nscore);
ex.setTitle(parts.front()->longName());
ex.setParts(parts);
::createExcerpt(&ex);
Excerpt* ex = new Excerpt(score);
ex->setPartScore(nscore);
nscore->setExcerpt(ex);
score->excerpts().append(ex);
ex->setTitle(parts.front()->longName());
ex->setParts(parts);
::createExcerpt(ex);
QVERIFY(nscore);
}
nscore->setName(parts.front()->partName());
nscore->style()->set(StyleIdx::createMultiMeasureRests, true);
@ -159,19 +157,20 @@ void TestChordSymbol::testNoSystem()
parts.clear();
parts.append(score->parts().at(1));
nscore = new Score(score);
score->Score::undo(new AddExcerpt(nscore));
{
Excerpt ex(score);
ex.setTitle(parts.front()->longName());
ex.setParts(parts);
ex.setPartScore(nscore);
::createExcerpt(&ex);
ex = new Excerpt(score);
ex->setPartScore(nscore);
nscore->setExcerpt(ex);
score->excerpts().append(ex);
ex->setTitle(parts.front()->longName());
ex->setParts(parts);
::createExcerpt(ex);
QVERIFY(nscore);
}
nscore->setName(parts.front()->partName());
nscore->style()->set(StyleIdx::createMultiMeasureRests, true);
score->setExcerptsChanged(true);
score->doLayout();
test_post(score, "no-system");
}

View file

@ -61,6 +61,7 @@ class TestParts : public QObject, public MTest
void createPart1();
void createPart2();
void voicesExcerpt();
void createPartBreath();
void addBreath();
@ -140,15 +141,16 @@ void TestParts::createParts(MasterScore* score)
parts.append(score->parts().at(0));
Score* nscore = new Score(score);
Excerpt ex(score);
ex.setPartScore(nscore);
ex.setTitle(parts.front()->longName());
ex.setParts(parts);
::createExcerpt(&ex);
Excerpt* ex = new Excerpt(score);
ex->setPartScore(nscore);
nscore->setExcerpt(ex);
score->excerpts().append(ex);
ex->setTitle(parts.front()->longName());
ex->setParts(parts);
::createExcerpt(ex);
QVERIFY(nscore);
nscore->setName(parts.front()->partName());
score->undo(new AddExcerpt(nscore));
//
// create second part
@ -156,14 +158,80 @@ void TestParts::createParts(MasterScore* score)
parts.clear();
parts.append(score->parts().at(1));
nscore = new Score(score);
ex.setTitle(parts.front()->longName());
ex.setPartScore(nscore);
ex.setParts(parts);
::createExcerpt(&ex);
ex = new Excerpt(score);
ex->setPartScore(nscore);
nscore->setExcerpt(ex);
score->excerpts().append(ex);
ex->setTitle(parts.front()->longName());
ex->setParts(parts);
::createExcerpt(ex);
QVERIFY(nscore);
nscore->setName(parts.front()->partName());
score->undo(new AddExcerpt(nscore));
score->setExcerptsChanged(true);
}
//---------------------------------------------------------
// voicesExcerpt
//---------------------------------------------------------
void TestParts::voicesExcerpt()
{
MasterScore* score = readScore(DIR + "voices.mscx");
//
// create first part
//
QList<Part*> parts;
QMultiMap<int, int> trackList;
parts.append(score->parts().at(0));
Score* nscore = new Score(score);
trackList.insert(1, 0);
trackList.insert(2, 1);
trackList.insert(4, 4);
Excerpt* ex = new Excerpt(score);
ex->setPartScore(nscore);
nscore->setExcerpt(ex);
score->excerpts().append(ex);
ex->setTitle(parts.front()->longName());
ex->setParts(parts);
ex->setTracks(trackList);
::createExcerpt(ex);
QVERIFY(nscore);
nscore->setName(parts.front()->partName());
//
// create second part
//
parts.clear();
parts.append(score->parts().at(1));
nscore = new Score(score);
trackList.clear();
trackList.insert(11, 0);
ex = new Excerpt(score);
ex->setPartScore(nscore);
nscore->setExcerpt(ex);
score->excerpts().append(ex);
ex->setTitle(parts.front()->longName());
ex->setParts(parts);
ex->setTracks(trackList);
::createExcerpt(ex);
QVERIFY(nscore);
nscore->setName(parts.front()->partName());
score->setExcerptsChanged(true);
QVERIFY(saveCompareScore(score, "voices.mscx", DIR + "voices-ref.mscx"));
delete score;
}
//---------------------------------------------------------

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,807 @@
<?xml version="1.0" encoding="UTF-8"?>
<museScore version="2.06">
<Score>
<LayerTag id="0" tag="default"></LayerTag>
<currentLayer>0</currentLayer>
<Division>480</Division>
<Style>
<lastSystemFillLimit>0</lastSystemFillLimit>
<page-layout>
<page-height>1683.78</page-height>
<page-width>1190.55</page-width>
<page-margins type="even">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
<page-margins type="odd">
<left-margin>56.6929</left-margin>
<right-margin>56.6929</right-margin>
<top-margin>56.6929</top-margin>
<bottom-margin>113.386</bottom-margin>
</page-margins>
</page-layout>
<Spatium>1.76389</Spatium>
</Style>
<showInvisible>1</showInvisible>
<showUnprintable>1</showUnprintable>
<showFrames>1</showFrames>
<showMargins>0</showMargins>
<metaTag name="arranger"></metaTag>
<metaTag name="composer"></metaTag>
<metaTag name="copyright"></metaTag>
<metaTag name="lyricist"></metaTag>
<metaTag name="movementNumber"></metaTag>
<metaTag name="movementTitle"></metaTag>
<metaTag name="poet"></metaTag>
<metaTag name="source"></metaTag>
<metaTag name="translator"></metaTag>
<metaTag name="workNumber"></metaTag>
<metaTag name="workTitle">voices</metaTag>
<PageList>
<Page>
<System>
</System>
<System>
</System>
</Page>
</PageList>
<Part>
<Staff id="1">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
<bracket type="1" span="2"/>
<barLineSpan>2</barLineSpan>
</Staff>
<Staff id="2">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
<defaultClef>F</defaultClef>
<bracket type="-1" span="0"/>
<barLineSpan>0</barLineSpan>
</Staff>
<trackName>Piano</trackName>
<Instrument>
<longName>Piano</longName>
<shortName>Pno.</shortName>
<trackName>Piano</trackName>
<minPitchP>21</minPitchP>
<maxPitchP>108</maxPitchP>
<minPitchA>21</minPitchA>
<maxPitchA>108</maxPitchA>
<instrumentId>keyboard.piano</instrumentId>
<clef staff="2">F</clef>
<Articulation>
<velocity>100</velocity>
<gateTime>95</gateTime>
</Articulation>
<Articulation name="staccatissimo">
<velocity>100</velocity>
<gateTime>33</gateTime>
</Articulation>
<Articulation name="staccato">
<velocity>100</velocity>
<gateTime>50</gateTime>
</Articulation>
<Articulation name="portato">
<velocity>100</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="tenuto">
<velocity>100</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="marcato">
<velocity>120</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="sforzato">
<velocity>120</velocity>
<gateTime>100</gateTime>
</Articulation>
<Channel>
<program value="0"/>
<midiPort>0</midiPort>
<midiChannel>2</midiChannel>
</Channel>
</Instrument>
</Part>
<Part>
<Staff id="3">
<StaffType group="pitched">
<name>stdNormal</name>
</StaffType>
<defaultClef>F</defaultClef>
<bracket type="-1" span="0"/>
</Staff>
<trackName>Trombone</trackName>
<Instrument>
<longName>Trombone</longName>
<shortName>Tbn.</shortName>
<trackName>Trombone</trackName>
<minPitchP>35</minPitchP>
<maxPitchP>74</maxPitchP>
<minPitchA>35</minPitchA>
<maxPitchA>70</maxPitchA>
<instrumentId>brass.trombone</instrumentId>
<clef>F</clef>
<Articulation>
<velocity>100</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="staccatissimo">
<velocity>100</velocity>
<gateTime>33</gateTime>
</Articulation>
<Articulation name="staccato">
<velocity>100</velocity>
<gateTime>50</gateTime>
</Articulation>
<Articulation name="portato">
<velocity>100</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="tenuto">
<velocity>100</velocity>
<gateTime>100</gateTime>
</Articulation>
<Articulation name="marcato">
<velocity>120</velocity>
<gateTime>67</gateTime>
</Articulation>
<Articulation name="sforzato">
<velocity>120</velocity>
<gateTime>100</gateTime>
</Articulation>
<Channel>
<program value="57"/>
<midiPort>0</midiPort>
<midiChannel>0</midiChannel>
</Channel>
</Instrument>
</Part>
<Staff id="1">
<VBox>
<height>10</height>
<Text>
<style>Title</style>
<text>voices</text>
</Text>
</VBox>
<Measure number="1">
<KeySig>
<accidental>-4</accidental>
</KeySig>
<TimeSig>
<sigN>4</sigN>
<sigD>4</sigD>
<showCourtesySig>1</showCourtesySig>
</TimeSig>
<Dynamic>
<subtype>pp</subtype>
<velocity>33</velocity>
</Dynamic>
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
<tick>0</tick>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>68</pitch>
<tpc>10</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>70</pitch>
<tpc>12</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Rest>
<track>1</track>
<durationType>quarter</durationType>
</Rest>
<tick>0</tick>
<Chord>
<track>2</track>
<durationType>quarter</durationType>
<Note>
<track>2</track>
<pitch>75</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>2</track>
<durationType>quarter</durationType>
<Note>
<track>2</track>
<pitch>77</pitch>
<tpc>13</tpc>
</Note>
</Chord>
<Chord>
<track>2</track>
<durationType>quarter</durationType>
<Note>
<track>2</track>
<pitch>79</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>2</track>
<durationType>quarter</durationType>
<Note>
<track>2</track>
<pitch>80</pitch>
<tpc>10</tpc>
</Note>
</Chord>
</Measure>
<Measure number="2">
<HairPin id="2">
<subtype>0</subtype>
<veloChange>10</veloChange>
<beginText>
<text>cresc.</text>
</beginText>
<continueText>
<text>(cresc.)</text>
</continueText>
</HairPin>
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
<tick>2400</tick>
<endSpanner id="2"/>
<tick>1920</tick>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<Fingering>
<pos x="1.05809" y="-4.67501"/>
<track>1</track>
<text>2</text>
</Fingering>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Articulation>
<subtype>sforzato</subtype>
<track>1</track>
</Articulation>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<tick>1920</tick>
<Rest>
<track>2</track>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
</Measure>
<Measure number="3">
<Harmony>
<root>11</root>
<name>7</name>
<pos x="0" y="-3.22581"/>
</Harmony>
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
<tick>3840</tick>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<tick>3840</tick>
<Chord>
<track>2</track>
<durationType>quarter</durationType>
<Note>
<track>2</track>
<pitch>75</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>2</track>
<durationType>quarter</durationType>
<Note>
<track>2</track>
<pitch>75</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>2</track>
<durationType>quarter</durationType>
<Note>
<track>2</track>
<pitch>75</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>2</track>
<durationType>quarter</durationType>
<Note>
<track>2</track>
<pitch>75</pitch>
<tpc>11</tpc>
</Note>
</Chord>
</Measure>
<Measure number="4">
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
<tick>5760</tick>
<Slur id="3">
<track>1</track>
</Slur>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Slur type="start" id="3"/>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Slur type="stop" id="3"/>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<tick>5760</tick>
<Rest>
<track>2</track>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
</Measure>
<Measure number="5">
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
<tick>7680</tick>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<Tie id="4">
<track>1</track>
</Tie>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<endSpanner id="4"/>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Chord>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<track>1</track>
<pitch>63</pitch>
<tpc>11</tpc>
</Note>
</Chord>
<Rest>
<track>1</track>
<durationType>quarter</durationType>
</Rest>
<tick>7680</tick>
<Rest>
<track>2</track>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
</Measure>
</Staff>
<Staff id="2">
<Measure number="1">
<TimeSig>
<sigN>4</sigN>
<sigD>4</sigD>
<showCourtesySig>1</showCourtesySig>
</TimeSig>
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
</Measure>
<Measure number="2">
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
</Measure>
<Measure number="3">
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>55</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>57</pitch>
<tpc>17</tpc>
</Note>
</Chord>
<Chord>
<durationType>quarter</durationType>
<Note>
<pitch>59</pitch>
<tpc>19</tpc>
</Note>
</Chord>
<Rest>
<durationType>quarter</durationType>
</Rest>
</Measure>
<Measure number="4">
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
</Measure>
<Measure number="5">
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
</Measure>
</Staff>
<Staff id="3">
<Measure number="1">
<TimeSig>
<sigN>4</sigN>
<sigD>4</sigD>
<showCourtesySig>1</showCourtesySig>
</TimeSig>
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
<tick>0</tick>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>48</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>50</pitch>
<tpc>16</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>52</pitch>
<tpc>18</tpc>
</Note>
</Chord>
<Rest>
<track>11</track>
<durationType>quarter</durationType>
</Rest>
</Measure>
<Measure number="2">
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
<tick>1920</tick>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<Fingering>
<pos x="1.05809" y="-4.67501"/>
<track>11</track>
<text>2</text>
</Fingering>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Articulation>
<subtype>sforzato</subtype>
<track>11</track>
</Articulation>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
</Measure>
<Measure number="3">
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
<tick>3840</tick>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
</Measure>
<Measure number="4">
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
<tick>5760</tick>
<Slur id="5">
<track>11</track>
</Slur>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Slur type="start" id="5"/>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Slur type="stop" id="5"/>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
</Measure>
<Measure number="5">
<Rest>
<durationType>measure</durationType>
<duration z="4" n="4"/>
</Rest>
<tick>7680</tick>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<Tie id="6">
<track>11</track>
</Tie>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<endSpanner id="6"/>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Chord>
<track>11</track>
<durationType>quarter</durationType>
<Note>
<track>11</track>
<pitch>43</pitch>
<tpc>15</tpc>
</Note>
</Chord>
<Rest>
<track>11</track>
<durationType>quarter</durationType>
</Rest>
</Measure>
</Staff>
</Score>
</museScore>

View file

@ -302,13 +302,16 @@ void TestSpanners::spanners05()
Excerpt ex(score);
ex.setPartScore(nscore);
nscore->setExcerpt(&ex);
ex.setTitle(parts.front()->longName());
ex.setParts(parts);
::createExcerpt(&ex);
QVERIFY(nscore);
nscore->setName(parts.front()->partName());
score->undo(new AddExcerpt(nscore));
QMultiMap<int, int> tracks;
score->Score::undo(new AddExcerpt(nscore, tracks));
QVERIFY(saveCompareScore(score, "glissando-cloning02.mscx", DIR + "glissando-cloning02-ref.mscx"));
delete score;

View file

@ -129,11 +129,11 @@
</Chord>
<move>0/1</move>
<Chord>
<lid>88</lid>
<lid>89</lid>
<track>1</track>
<durationType>whole</durationType>
<Note>
<lid>89</lid>
<lid>90</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -142,16 +142,16 @@
</Measure>
<Measure number="2">
<Rest>
<lid>93</lid>
<lid>94</lid>
<durationType>whole</durationType>
</Rest>
<move>0/1</move>
<Chord>
<lid>91</lid>
<lid>92</lid>
<track>1</track>
<durationType>whole</durationType>
<Note>
<lid>92</lid>
<lid>93</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -189,18 +189,18 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>94</lid>
<lid>95</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<lid>95</lid>
<lid>96</lid>
<track>1</track>
<durationType>half</durationType>
<Note>
<lid>96</lid>
<lid>97</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -245,11 +245,11 @@
</Chord>
<move>1/2</move>
<Chord>
<lid>98</lid>
<lid>99</lid>
<track>1</track>
<durationType>half</durationType>
<Note>
<lid>99</lid>
<lid>100</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -324,27 +324,27 @@
</Note>
</Chord>
<Rest>
<lid>106</lid>
<lid>107</lid>
<durationType>quarter</durationType>
</Rest>
<move>0/1</move>
<Chord>
<lid>101</lid>
<lid>102</lid>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<lid>102</lid>
<lid>103</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<lid>103</lid>
<lid>104</lid>
<track>1</track>
<durationType>half</durationType>
<Note>
<lid>104</lid>
<lid>105</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -361,7 +361,7 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>105</lid>
<lid>106</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -390,7 +390,7 @@
</Note>
</Chord>
<Rest>
<lid>109</lid>
<lid>110</lid>
<Tuplet>1</Tuplet>
<durationType>quarter</durationType>
</Rest>
@ -512,7 +512,7 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>107</lid>
<lid>108</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -530,19 +530,19 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>108</lid>
<lid>109</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<lid>110</lid>
<lid>111</lid>
<track>1</track>
<Tuplet>3</Tuplet>
<durationType>quarter</durationType>
<Note>
<lid>111</lid>
<lid>112</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -572,7 +572,7 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>112</lid>
<lid>113</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -590,13 +590,13 @@
<l2>24</l2>
</Beam>
<Chord>
<lid>113</lid>
<lid>114</lid>
<track>1</track>
<Tuplet>4</Tuplet>
<durationType>eighth</durationType>
<Beam>2</Beam>
<Note>
<lid>114</lid>
<lid>115</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -615,7 +615,7 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>115</lid>
<lid>116</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -748,11 +748,11 @@
</Chord>
<move>0/1</move>
<Chord>
<lid>88</lid>
<lid>89</lid>
<track>1</track>
<durationType>whole</durationType>
<Note>
<lid>89</lid>
<lid>90</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -761,16 +761,16 @@
</Measure>
<Measure number="2">
<Rest>
<lid>93</lid>
<lid>94</lid>
<durationType>whole</durationType>
</Rest>
<move>0/1</move>
<Chord>
<lid>91</lid>
<lid>92</lid>
<track>1</track>
<durationType>whole</durationType>
<Note>
<lid>92</lid>
<lid>93</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -808,18 +808,18 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>94</lid>
<lid>95</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<lid>95</lid>
<lid>96</lid>
<track>1</track>
<durationType>half</durationType>
<Note>
<lid>96</lid>
<lid>97</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -864,11 +864,11 @@
</Chord>
<move>1/2</move>
<Chord>
<lid>98</lid>
<lid>99</lid>
<track>1</track>
<durationType>half</durationType>
<Note>
<lid>99</lid>
<lid>100</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -943,27 +943,27 @@
</Note>
</Chord>
<Rest>
<lid>106</lid>
<lid>107</lid>
<durationType>quarter</durationType>
</Rest>
<move>0/1</move>
<Chord>
<lid>101</lid>
<lid>102</lid>
<track>1</track>
<durationType>quarter</durationType>
<Note>
<lid>102</lid>
<lid>103</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<lid>103</lid>
<lid>104</lid>
<track>1</track>
<durationType>half</durationType>
<Note>
<lid>104</lid>
<lid>105</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -980,7 +980,7 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>105</lid>
<lid>106</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -1009,7 +1009,7 @@
</Note>
</Chord>
<Rest>
<lid>109</lid>
<lid>110</lid>
<Tuplet>5</Tuplet>
<durationType>quarter</durationType>
</Rest>
@ -1131,7 +1131,7 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>107</lid>
<lid>108</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -1149,19 +1149,19 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>108</lid>
<lid>109</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
</Note>
</Chord>
<Chord>
<lid>110</lid>
<lid>111</lid>
<track>1</track>
<Tuplet>7</Tuplet>
<durationType>quarter</durationType>
<Note>
<lid>111</lid>
<lid>112</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -1191,7 +1191,7 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>112</lid>
<lid>113</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -1209,13 +1209,13 @@
<l2>24</l2>
</Beam>
<Chord>
<lid>113</lid>
<lid>114</lid>
<track>1</track>
<Tuplet>8</Tuplet>
<durationType>eighth</durationType>
<Beam>4</Beam>
<Note>
<lid>114</lid>
<lid>115</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>
@ -1234,7 +1234,7 @@
<tpc>15</tpc>
</Note>
<Note>
<lid>115</lid>
<lid>116</lid>
<track>1</track>
<pitch>72</pitch>
<tpc>14</tpc>