From 48d02c7ee409234d313bc44010afbafe925ce32f Mon Sep 17 00:00:00 2001 From: Marc Sabatella Date: Fri, 5 Apr 2019 23:54:38 -0600 Subject: [PATCH] fix #283828: add end-start repeat --- libmscore/barline.cpp | 81 ++++++++++++++++++++++++--- libmscore/barline.h | 2 +- libmscore/cmd.cpp | 10 +++- libmscore/layout.cpp | 1 + libmscore/measure.cpp | 10 ++++ libmscore/mscore.h | 1 + libmscore/read114.cpp | 4 +- mscore/capella.cpp | 8 +-- mscore/capxml.cpp | 2 +- mscore/exportxml.cpp | 5 +- mscore/importgtp.cpp | 3 +- mscore/importove.cpp | 3 +- mscore/inspector/inspectorBarline.cpp | 8 +-- mscore/menus.cpp | 1 + mscore/timeline.cpp | 3 + share/workspaces/Advanced.xml | 14 ++++- share/workspaces/Basic.xml | 22 ++++++-- 17 files changed, 143 insertions(+), 35 deletions(-) diff --git a/libmscore/barline.cpp b/libmscore/barline.cpp index 1fb346bcb03d7..d649e62c09f9e 100644 --- a/libmscore/barline.cpp +++ b/libmscore/barline.cpp @@ -38,13 +38,13 @@ static void undoChangeBarLineType(BarLine* bl, BarLineType barType, bool allStav Measure* m = bl->measure(); if (barType == BarLineType::START_REPEAT) { - m->undoChangeProperty(Pid::REPEAT_END, false); m = m->nextMeasure(); if (!m) return; } else if (bl->barLineType() == BarLineType::START_REPEAT) { - m->undoChangeProperty(Pid::REPEAT_START, false); + if (barType != BarLineType::END_REPEAT) + m->undoChangeProperty(Pid::REPEAT_START, false); m = m->prevMeasure(); if (!m) return; @@ -135,6 +135,17 @@ static void undoChangeBarLineType(BarLine* bl, BarLineType barType, bool allStav } } break; + case BarLineType::END_START_REPEAT: { + Measure* m2 = m->isMMRest() ? m->mmRestLast() : m; + for (Score* lscore : m2->score()->scoreList()) { + Measure* lmeasure = lscore->tick2measure(m2->tick()); + lmeasure->undoChangeProperty(Pid::REPEAT_END, true); + lmeasure = lmeasure->nextMeasure(); + if (lmeasure) + lmeasure->undoChangeProperty(Pid::REPEAT_START, true); + } + } + break; } } @@ -159,6 +170,7 @@ const std::vector BarLine::barLineTable { { BarLineType::END_REPEAT, QT_TRANSLATE_NOOP("Palette", "End repeat"), "end-repeat" }, { BarLineType::BROKEN, QT_TRANSLATE_NOOP("Palette", "Dashed barline"), "dashed" }, { BarLineType::END, QT_TRANSLATE_NOOP("Palette", "Final barline"), "end" }, + { BarLineType::END_START_REPEAT, QT_TRANSLATE_NOOP("Palette", "End-start repeat"), "end-start-repeat" }, { BarLineType::DOTTED, QT_TRANSLATE_NOOP("Palette", "Dotted barline"), "dotted" }, }; @@ -525,6 +537,38 @@ void BarLine::draw(QPainter* painter) const drawTips(painter, true, x + lw2 * .5); } break; + case BarLineType::END_START_REPEAT: { + qreal lw = score()->styleP(Sid::barWidth) * mag(); + painter->setPen(QPen(curColor(), lw, Qt::SolidLine, Qt::FlatCap)); + + qreal x = 0.0; // symBbox(SymId::repeatDot).width() * .5; + drawDots(painter, x); + + x += score()->styleP(Sid::repeatBarlineDotSeparation) * mag(); + x += symBbox(SymId::repeatDot).width() * .5; + painter->drawLine(QLineF(x, y1, x, y2)); + + x += score()->styleP(Sid::endBarDistance) * mag(); + + qreal lw2 = score()->styleP(Sid::endBarWidth) * mag(); + painter->setPen(QPen(curColor(), lw2, Qt::SolidLine, Qt::FlatCap)); + painter->drawLine(QLineF(x, y1, x, y2)); + + if (score()->styleB(Sid::repeatBarTips)) + drawTips(painter, true, x + lw2 * .5); + + painter->setPen(QPen(curColor(), lw, Qt::SolidLine, Qt::FlatCap)); + x += score()->styleP(Sid::endBarDistance) * mag(); + painter->drawLine(QLineF(x, y1, x, y2)); + + x += score()->styleP(Sid::repeatBarlineDotSeparation) * mag(); + x -= symBbox(SymId::repeatDot).width() * .5; + drawDots(painter, x); + + if (score()->styleB(Sid::repeatBarTips)) + drawTips(painter, false, 0.0); + } + break; } Segment* s = segment(); if (s && s->isEndBarLineType() && !score()->printing() && score()->showUnprintable()) { @@ -647,7 +691,7 @@ Element* BarLine::drop(EditData& data) } // check if the new property can apply to this single bar line - BarLineType bt = BarLineType::START_REPEAT | BarLineType::END_REPEAT; + BarLineType bt = BarLineType::START_REPEAT | BarLineType::END_REPEAT | BarLineType::END_START_REPEAT; bool oldRepeat = barLineType() & bt; bool newRepeat = bl->barLineType() & bt; @@ -668,11 +712,13 @@ Element* BarLine::drop(EditData& data) undoChangeProperty(Pid::BARLINE_SPAN_TO, spanTo); } // if drop refers to subtype, update this bar line subtype - else + else { undoChangeBarLineType(this, st, false); + } } - else + else { undoChangeBarLineType(this, st, true); + } delete e; } else if (e->isArticulation()) { @@ -1024,6 +1070,11 @@ qreal BarLine::layoutWidth(Score* score, BarLineType type) case BarLineType::DOUBLE: w = score->styleP(Sid::doubleBarWidth) + score->styleP(Sid::doubleBarDistance); break; + case BarLineType::END_START_REPEAT: + w = score->styleP(Sid::endBarDistance) * 2 + + score->styleP(Sid::repeatBarlineDotSeparation) * 2 + + dotwidth; + break; case BarLineType::START_REPEAT: case BarLineType::END_REPEAT: w = score->styleP(Sid::endBarWidth) * .5 @@ -1075,11 +1126,18 @@ void BarLine::layout() // r |= symBbox(SymId::bracketBottom).translated(0, y2); break; case BarLineType::END_REPEAT: { - qreal w1 = symBbox(SymId::reversedBracketTop).width(); + qreal w1 = 0.0; //symBbox(SymId::reversedBracketTop).width(); r |= symBbox(SymId::reversedBracketTop).translated(-w1, y1); // r |= symBbox(SymId::reversedBracketBottom).translated(0, y2); } break; + case BarLineType::END_START_REPEAT: { + qreal w1 = 0.0; //symBbox(SymId::reversedBracketTop).width(); + r |= symBbox(SymId::reversedBracketTop).translated(-w1, y1); + r |= symBbox(SymId::bracketTop).translated(0, y1); + // r |= symBbox(SymId::reversedBracketBottom).translated(0, y2); + } + break; default: break; } @@ -1133,11 +1191,20 @@ void BarLine::layout2() break; case BarLineType::END_REPEAT: { - qreal w1 = symBbox(SymId::reversedBracketTop).width(); + qreal w1 = 0.0; //symBbox(SymId::reversedBracketTop).width(); bbox() |= symBbox(SymId::reversedBracketTop).translated(-w1, y1); bbox() |= symBbox(SymId::reversedBracketBottom).translated(-w1, y2); break; } + case BarLineType::END_START_REPEAT: + { + qreal w1 = 0.0; //symBbox(SymId::reversedBracketTop).width(); + bbox() |= symBbox(SymId::reversedBracketTop).translated(-w1, y1); + bbox() |= symBbox(SymId::reversedBracketBottom).translated(-w1, y2); + bbox() |= symBbox(SymId::bracketTop).translated(0, y1); + bbox() |= symBbox(SymId::bracketBottom).translated(0, y2); + break; + } default: break; } diff --git a/libmscore/barline.h b/libmscore/barline.h index 370afef127e85..048bbe4ff8ef9 100644 --- a/libmscore/barline.h +++ b/libmscore/barline.h @@ -51,7 +51,7 @@ struct BarLineTableItem { //--------------------------------------------------------- // @@ BarLine // -// @P barLineType enum (BarLineType.NORMAL, .DOUBLE, .START_REPEAT, .END_REPEAT, .BROKEN, .END, .DOTTED) +// @P barLineType enum (BarLineType.NORMAL, .DOUBLE, .START_REPEAT, .END_REPEAT, .BROKEN, .END, .END_START_REPEAT, .DOTTED) //--------------------------------------------------------- class BarLine final : public Element { diff --git a/libmscore/cmd.cpp b/libmscore/cmd.cpp index acb7934e972ee..7bcbe8b0996bc 100644 --- a/libmscore/cmd.cpp +++ b/libmscore/cmd.cpp @@ -3254,14 +3254,20 @@ void Score::cmdToggleLayoutBreak(LayoutBreak::Type type) default: { // find measure Measure* measure = toMeasure(el->findMeasure()); + // for start repeat, attach brek to previous measure + if (el->isBarLine()) { + BarLine* bl = toBarLine(el); + if (bl->barLineType() == BarLineType::START_REPEAT) + measure = measure->prevMeasure(); + } // if measure is mmrest, then propagate to last original measure if (measure) mb = measure->isMMRest() ? measure->mmRestLast() : measure; } } } - if (mb) - mbl.append(mb); + if (mb) + mbl.append(mb); } // toggle the breaks for (MeasureBase* mb: mbl) { diff --git a/libmscore/layout.cpp b/libmscore/layout.cpp index 22178563b3d0b..83017dc9dabf1 100644 --- a/libmscore/layout.cpp +++ b/libmscore/layout.cpp @@ -3600,6 +3600,7 @@ void Score::layoutSystemElements(System* system, LayoutContext& lc) BarLine* bl = toBarLine(s.element(0)); if (bl) { qreal w = BarLine::layoutWidth(score(), bl->barLineType()); + // TODO: actual vertical position and height for staff? skyline.add(QRectF(0.0, 0.0, w, spatium() * 4.0).translated(bl->pos() + p)); } } diff --git a/libmscore/measure.cpp b/libmscore/measure.cpp index 8f4463cf5650e..9db50d61d6128 100644 --- a/libmscore/measure.cpp +++ b/libmscore/measure.cpp @@ -1551,6 +1551,16 @@ Element* Measure::drop(EditData& data) lmeasure->undoChangeProperty(Pid::REPEAT_END, true); } } + else if (bl->barLineType() == BarLineType::END_START_REPEAT) { + Measure* m2 = isMMRest() ? mmRestLast() : this; + for (Score* lscore : score()->scoreList()) { + Measure* lmeasure = lscore->tick2measure(m2->tick()); + lmeasure->undoChangeProperty(Pid::REPEAT_END, true); + lmeasure = lmeasure->nextMeasure(); + if (lmeasure) + lmeasure->undoChangeProperty(Pid::REPEAT_START, true); + } + } else { // drop to first end barline seg = findSegmentR(SegmentType::EndBarLine, ticks()); diff --git a/libmscore/mscore.h b/libmscore/mscore.h index 43ba22e3b75af..7a2554e5f7dcc 100644 --- a/libmscore/mscore.h +++ b/libmscore/mscore.h @@ -228,6 +228,7 @@ enum class BarLineType { END_REPEAT = 8, BROKEN = 0x10, END = 0x20, + END_START_REPEAT = 0x40, DOTTED = 0x80 }; diff --git a/libmscore/read114.cpp b/libmscore/read114.cpp index ac40daa05c205..22c76f8a50281 100644 --- a/libmscore/read114.cpp +++ b/libmscore/read114.cpp @@ -81,7 +81,7 @@ static const StyleVal2 style114[] = { { Sid::lyricsDashForce, QVariant(false) }, { Sid::frameSystemDistance, Spatium(1.0) }, { Sid::minMeasureWidth, Spatium(4.0) }, - { Sid::endBarDistance, Spatium(0.30) }, +// { Sid::endBarDistance, Spatium(0.30) }, { Sid::repeatBarTips, QVariant(false) }, { Sid::startBarlineSingle, QVariant(false) }, @@ -1586,7 +1586,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e) t = BarLineType::END; break; case 6: - // TODO t = BarLineType::END_START_REPEAT; + t = BarLineType::END_START_REPEAT; break; } barLine->setBarLineType(t); diff --git a/mscore/capella.cpp b/mscore/capella.cpp index 13b9e3d2a57fb..7144414e324dd 100644 --- a/mscore/capella.cpp +++ b/mscore/capella.cpp @@ -893,8 +893,7 @@ static Fraction readCapVoice(Score* score, CapVoice* cvoice, int staffIdx, const //TODO if (pm && (st == BarLineType::DOUBLE || st == BarLineType::END || st == BarLineType::BROKEN)) // pm->setEndBarLineType(st, false, true); -//TODO if (st == BarLineType::START_REPEAT || st == BarLineType::END_START_REPEAT) { - if (st == BarLineType::START_REPEAT) { + if (st == BarLineType::START_REPEAT || st == BarLineType::END_START_REPEAT) { Measure* nm = 0; // the next measure (the one started by this barline) nm = score->getCreateMeasure(tick); // qDebug("nm %p", nm); @@ -902,8 +901,7 @@ static Fraction readCapVoice(Score* score, CapVoice* cvoice, int staffIdx, const nm->setRepeatStart(true); } -// if (st == BarLineType::END_REPEAT || st == BarLineType::END_START_REPEAT) { - if (st == BarLineType::END_REPEAT) { + if (st == BarLineType::END_REPEAT || st == BarLineType::END_START_REPEAT) { if (pm) pm->setRepeatEnd(true); } @@ -2411,7 +2409,7 @@ void CapExplicitBarline::read() else if (type == 2) _type = BarLineType::END; else if (type == 3) _type = BarLineType::END_REPEAT; else if (type == 4) _type = BarLineType::START_REPEAT; -//TODO else if (type == 5) _type = BarLineType::END_START_REPEAT; + else if (type == 5) _type = BarLineType::END_START_REPEAT; else if (type == 6) _type = BarLineType::BROKEN; else _type = BarLineType::NORMAL; // default _barMode = b >> 4; // 0 = auto, 1 = nur Zeilen, 2 = durchgezogen diff --git a/mscore/capxml.cpp b/mscore/capxml.cpp index 28c3c261e59b1..b2cd7588be5ea 100644 --- a/mscore/capxml.cpp +++ b/mscore/capxml.cpp @@ -165,7 +165,7 @@ void CapExplicitBarline::readCapx(XmlReader& e) else if (type == "end") _type = BarLineType::END; else if (type == "repEnd") _type = BarLineType::END_REPEAT; else if (type == "repBegin") _type = BarLineType::START_REPEAT; -//TODO else if (type == "repEndBegin") _type = BarLineType::END_START_REPEAT; + else if (type == "repEndBegin") _type = BarLineType::END_START_REPEAT; else if (type == "dashed") _type = BarLineType::BROKEN; else _type = BarLineType::NORMAL; // default _barMode = 0; diff --git a/mscore/exportxml.cpp b/mscore/exportxml.cpp index 2b9a808dc7707..41bfaa6c9067a 100644 --- a/mscore/exportxml.cpp +++ b/mscore/exportxml.cpp @@ -1572,7 +1572,7 @@ void ExportMusicXml::barlineRight(Measure* m) _xml.tag("bar-style", QString("dotted")); break; case BarLineType::END: -// case BarLineType::END_START_REPEAT: + case BarLineType::END_START_REPEAT: _xml.tag("bar-style", QString("light-heavy")); break; default: @@ -1586,8 +1586,7 @@ void ExportMusicXml::barlineRight(Measure* m) } if (volta) ending(_xml, volta, false); -// if (bst == BarLineType::END_REPEAT || bst == BarLineType::END_START_REPEAT) - if (bst == BarLineType::END_REPEAT) + if (bst == BarLineType::END_REPEAT || bst == BarLineType::END_START_REPEAT) { if (m->repeatCount() > 2) { _xml.tagE(QString("repeat direction=\"backward\" times=\"%1\"").arg(m->repeatCount())); diff --git a/mscore/importgtp.cpp b/mscore/importgtp.cpp index bdbfeee66c934..ac14f581d9910 100644 --- a/mscore/importgtp.cpp +++ b/mscore/importgtp.cpp @@ -2829,8 +2829,7 @@ Score::FileError importGTP(MasterScore* score, const QString& name) for (Measure* m1 = score->firstMeasure(); m1; m1 = m1->nextMeasure(), ++idx) { const GpBar& bar = gp->bars[idx]; - //TODO if (bar.barLine != BarLineType::NORMAL && bar.barLine != BarLineType::END_REPEAT && bar.barLine != BarLineType::START_REPEAT && bar.barLine != BarLineType::END_START_REPEAT) - if (bar.barLine != BarLineType::NORMAL && bar.barLine != BarLineType::END_REPEAT && bar.barLine != BarLineType::START_REPEAT) + if (bar.barLine != BarLineType::NORMAL && bar.barLine != BarLineType::END_REPEAT && bar.barLine != BarLineType::START_REPEAT && bar.barLine != BarLineType::END_START_REPEAT) m1->setEndBarLineType(bar.barLine, 0); } if (score->lastMeasure() && score->lastMeasure()->endBarLineType() != BarLineType::NORMAL) diff --git a/mscore/importove.cpp b/mscore/importove.cpp index 49eba532277cb..3efd15800730a 100644 --- a/mscore/importove.cpp +++ b/mscore/importove.cpp @@ -1254,8 +1254,7 @@ void OveToMScore::convertMeasureMisc(Measure* measure, int part, int staff, int break; } -//TODO if (bartype != BarLineType::NORMAL && bartype != BarLineType::END_REPEAT && bartype != BarLineType::START_REPEAT && bartype != BarLineType::END_START_REPEAT && bartype != BarLineType::END) - if (bartype != BarLineType::NORMAL && bartype != BarLineType::END_REPEAT && bartype != BarLineType::START_REPEAT && bartype != BarLineType::END) + if (bartype != BarLineType::NORMAL && bartype != BarLineType::END_REPEAT && bartype != BarLineType::START_REPEAT && bartype != BarLineType::END_START_REPEAT && bartype != BarLineType::END) measure->setEndBarLineType(bartype, 0); if (bartype == BarLineType::END_REPEAT) diff --git a/mscore/inspector/inspectorBarline.cpp b/mscore/inspector/inspectorBarline.cpp index e28ca501d7b07..b2afe0c73a50c 100644 --- a/mscore/inspector/inspectorBarline.cpp +++ b/mscore/inspector/inspectorBarline.cpp @@ -91,16 +91,16 @@ void InspectorBarLine::setElement() // enable / disable individual type combo items according to score and selected bar line status bool bMultiStaff = bl->score()->nstaves() > 1; BarLineType blt = bl->barLineType(); -// bool isRepeat = blt & (BarLineType::START_REPEAT | BarLineType::END_REPEAT | BarLineType::END_START_REPEAT); - bool isRepeat = blt & (BarLineType::START_REPEAT | BarLineType::END_REPEAT); + bool isRepeat = blt & (BarLineType::START_REPEAT | BarLineType::END_REPEAT | BarLineType::END_START_REPEAT); +// bool isRepeat = blt & (BarLineType::START_REPEAT | BarLineType::END_REPEAT); const QStandardItemModel* model = qobject_cast(b.type->model()); int i = 0; for (auto& k : BarLine::barLineTable) { QStandardItem* item = model->item(i); // if combo item is repeat type, should be disabled for multi-staff scores -// if (k.type & (BarLineType::START_REPEAT | BarLineType::END_REPEAT | BarLineType::END_START_REPEAT)) { - if (k.type & (BarLineType::START_REPEAT | BarLineType::END_REPEAT)) { + if (k.type & (BarLineType::START_REPEAT | BarLineType::END_REPEAT | BarLineType::END_START_REPEAT)) { +// if (k.type & (BarLineType::START_REPEAT | BarLineType::END_REPEAT)) { // disable / enable item->setFlags(bMultiStaff ? item->flags() & ~(Qt::ItemIsSelectable|Qt::ItemIsEnabled) : diff --git a/mscore/menus.cpp b/mscore/menus.cpp index cfe0d3bc1eac7..cd2316325a6e0 100644 --- a/mscore/menus.cpp +++ b/mscore/menus.cpp @@ -382,6 +382,7 @@ Palette* MuseScore::newRepeatsPalette() switch (bti->type) { case BarLineType::START_REPEAT: case BarLineType::END_REPEAT: + case BarLineType::END_START_REPEAT: break; default: continue; diff --git a/mscore/timeline.cpp b/mscore/timeline.cpp index 0fbef8538734c..82f429857c897 100644 --- a/mscore/timeline.cpp +++ b/mscore/timeline.cpp @@ -1231,6 +1231,9 @@ void Timeline::barline_meta(Segment* seg, int* stagger, int pos) case BarLineType::END_REPEAT: repeat_text = QString("End repeat"); break; + case BarLineType::END_START_REPEAT: + repeat_text = QString("End-start repeat"); + break; case BarLineType::DOUBLE: repeat_text = QString("Double barline"); break; diff --git a/share/workspaces/Advanced.xml b/share/workspaces/Advanced.xml index 833e3a4004955..8ea90556f2014 100644 --- a/share/workspaces/Advanced.xml +++ b/share/workspaces/Advanced.xml @@ -1276,6 +1276,12 @@ end-repeat + + 1 + + end-start-repeat + + 1 @@ -2175,7 +2181,13 @@ end-repeat - + + 1 + + end-start-repeat + + + 42 45 diff --git a/share/workspaces/Basic.xml b/share/workspaces/Basic.xml index c341d19b29fbf..eda9d22887bb3 100644 --- a/share/workspaces/Basic.xml +++ b/share/workspaces/Basic.xml @@ -48,7 +48,7 @@ 1 - voiceActions + 1 @@ -204,7 +204,7 @@ 1 - voiceActions + 1 4 4 @@ -357,7 +357,7 @@ 2 cresc. - (cresc.)voiceActions + (cresc.) 0 @@ -387,7 +387,7 @@ 0 200 2 - voiceActions + @@ -465,7 +465,13 @@ 1 end-repeat - voiceActions + + + + 1 + + end-start-repeat + 1 @@ -776,6 +782,12 @@ end-repeat + + 1 + + end-start-repeat + + 42