Skip to content

Commit

Permalink
Re-enable NOBREAK with fixes and new functionality
Browse files Browse the repository at this point in the history
- Fix #279071: "Don't Break" element creates hole at end of system
- Allow more than two measures to be grouped
- Allow adding/toggling NOBREAK by clicking palette
- Rename to "Group Measures"
- Adjust placement of break symbols
Co-authored-by: MarcSabatella <marc@outsideshore.com>

Backport of musescore#6365, commit 1, plus some includes cleanup
  • Loading branch information
IsaacWeiss authored and Jojo-Schmitz committed Jun 26, 2024
1 parent 4b431b4 commit fa50d4c
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 210 deletions.
54 changes: 40 additions & 14 deletions libmscore/cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3877,28 +3877,41 @@ void Score::cmdToggleLayoutBreak(LayoutBreak::Type type)
{
// find measure(s)
QList<MeasureBase*> mbl;
bool allNoBreaks = true; // NOBREAK is not removed unless every measure in selection already has one
if (selection().isRange()) {
Measure* startMeasure = nullptr;
Measure* endMeasure = nullptr;
if (!selection().measureRange(&startMeasure, &endMeasure))
return;
if (!startMeasure || !endMeasure)
return;
#if 1
// toggle break on the last measure of the range
mbl.append(endMeasure);
// if more than one measure selected,
// also toggle break *before* the range (to try to fit selection on a single line)
if (startMeasure != endMeasure && startMeasure->prev())
mbl.append(startMeasure->prev());
#else
// toggle breaks throughout the selection
for (Measure* m = startMeasure; m; m = m->nextMeasure()) {
mbl.append(m);
if (m == endMeasure)
break;
if (type == LayoutBreak::Type::NOBREAK) {
// add throughout the selection
// or remove if already on every measure
if (startMeasure == endMeasure) {
mbl.append(startMeasure);
allNoBreaks = startMeasure->noBreak();
}
else {
for (Measure* m = startMeasure; m; m = m->nextMeasureMM()) {
mbl.append(m);
if (m == endMeasure) {
mbl.pop_back();
break;
}
if (!toMeasureBase(m)->noBreak())
allNoBreaks = false;
}
}
}
else {
// toggle break on the last measure of the range
mbl.append(endMeasure);
// if more than one measure selected,
// also toggle break *before* the range (to try to fit selection on a single line)
if (startMeasure != endMeasure && startMeasure->prev())
mbl.append(startMeasure->prev());
}
#endif
}
else {
MeasureBase* mb = nullptr;
Expand All @@ -3921,6 +3934,7 @@ void Score::cmdToggleLayoutBreak(LayoutBreak::Type type)
// if measure is mmrest, then propagate to last original measure
if (measure)
mb = measure->isMMRest() ? measure->mmRestLast() : measure;
allNoBreaks = mb->noBreak();
}
}
}
Expand Down Expand Up @@ -3950,6 +3964,18 @@ void Score::cmdToggleLayoutBreak(LayoutBreak::Type type)
val = !mb->sectionBreak();
mb->undoSetBreak(val, type);
break;
case LayoutBreak::Type::NOBREAK:
mb->undoSetBreak(!allNoBreaks, type);
// remove other breaks if appropriate
if (!mb->noBreak()) {
if (mb->pageBreak())
mb->undoSetBreak(false, LayoutBreak::Type::PAGE);
else if (mb->lineBreak())
mb->undoSetBreak(false, LayoutBreak::Type::LINE);
else if (mb->sectionBreak())
mb->undoSetBreak(false, LayoutBreak::Type::SECTION);
}
break;
default:
break;
}
Expand Down
72 changes: 48 additions & 24 deletions libmscore/layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3980,9 +3980,9 @@ System* Score::collectSystem(LayoutContext& lc)
system->setWidth(systemWidth);

// save state of measure
qreal curWidth = lc.curMeasure->width();
bool curHeader = lc.curMeasure->header();
bool curTrailer = lc.curMeasure->trailer();
MeasureBase* breakMeasure = nullptr;

QList<System *> brokenSystems;

Expand Down Expand Up @@ -4017,7 +4017,13 @@ System* Score::collectSystem(LayoutContext& lc)
}

m->createEndBarLines(true);
m->addSystemTrailer(m->nextMeasure());
// measures with nobreak cannot end a system
// thus they will not contain a trailer
if (m->noBreak())
m->removeSystemTrailer();
else
m->addSystemTrailer(m->nextMeasure());

m->computeMinWidth();
ww = m->width();
}
Expand All @@ -4037,24 +4043,27 @@ System* Score::collectSystem(LayoutContext& lc)

bool doBreak = (system->measures().size() > 1) && ((minWidth + ww) > systemWidth);
if (doBreak) {
if (lc.prevMeasure->noBreak() && system->measures().size() > 2) {
// remove last two measures
// TODO: check more measures for noBreak()
system->removeLastMeasure();
system->removeLastMeasure();
breakMeasure = lc.curMeasure;
system->removeLastMeasure();
lc.curMeasure->setSystem(oldSystem);
while (lc.prevMeasure && lc.prevMeasure->noBreak() && system->measures().size() > 1) {
// remove however many measures are grouped with nobreak, working backwards
// but if too many are grouped, stop before we get 0 measures left on system
// TODO: intelligently break group into smaller groups instead
lc.tick -= lc.curMeasure->ticks();
--lc.measureNo;

lc.curMeasure->setSystem(oldSystem);
lc.prevMeasure->setSystem(oldSystem);
lc.nextMeasure = lc.curMeasure;
lc.curMeasure = lc.prevMeasure;
lc.prevMeasure = lc.curMeasure->prevMeasure();
break;
}
else if (!lc.prevMeasure->noBreak()) {
// remove last measure

minWidth -= system->lastMeasure()->width();
system->removeLastMeasure();
lc.curMeasure->setSystem(oldSystem);
break;
}
break;
}

if (oldSystem && system != oldSystem && !brokenSystems.contains(oldSystem)
Expand Down Expand Up @@ -4121,9 +4130,17 @@ System* Score::collectSystem(LayoutContext& lc)
if (nm->hasMMRest())
nmb = nm->mmRest();
}
curWidth = nmb->width();
curHeader = nmb->header();
curTrailer = nmb->trailer();
nmb->setOldWidth(nmb->width());
if (!lc.curMeasure->noBreak()) {
// current measure is not a nobreak,
// so next measure could possibly start a system
curHeader = nmb->header();
}
if (!nmb->noBreak()) {
// next measure is not a nobreak
// so it could possibly end a system
curTrailer = nmb->trailer();
}
}

getNextMeasure(lc);
Expand All @@ -4144,8 +4161,8 @@ System* Score::collectSystem(LayoutContext& lc)
// this system ends in the same place as the previous layout
// ok to stop
if (lc.curMeasure && lc.curMeasure->isMeasure()) {
// we may have previously processed first measure of next system
// so now we must restore it to its original state
// we may have previously processed first measure(s) of next system
// so now we must restore to original state
Measure* m = toMeasure(lc.curMeasure);
if (m->repeatStart()) {
Segment* s = m->findSegmentR(SegmentType::StartRepeatBarLine, Fraction(0,1));
Expand All @@ -4154,17 +4171,24 @@ System* Score::collectSystem(LayoutContext& lc)
}
const MeasureBase* pbmb = lc.prevMeasure->findPotentialSectionBreak();
bool firstSystem = pbmb->sectionBreak() && _layoutMode != LayoutMode::FLOAT;
MeasureBase* nm = breakMeasure ? breakMeasure : m;
if (curHeader)
m->addSystemHeader(firstSystem);
else
m->removeSystemHeader();
if (curTrailer)
m->addSystemTrailer(m->nextMeasure());
else
m->removeSystemTrailer();
m->computeMinWidth();
m->stretchMeasure(curWidth);
restoreBeams(m);
for (;;) {
// TODO: what if the nobreak group takes the entire system - is this correct?
if (curTrailer && !m->noBreak())
m->addSystemTrailer(m->nextMeasure());
else
m->removeSystemTrailer();
m->computeMinWidth();
m->stretchMeasure(m->oldWidth());
restoreBeams(m);
if (m == nm || !m->noBreak())
break;
m = m->nextMeasure();
}
}
lc.rangeDone = true;
}
Expand Down
26 changes: 11 additions & 15 deletions libmscore/measurebase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,17 @@
// the file LICENCE.GPL
//=============================================================================

#include "measurebase.h"
#include "layoutbreak.h"
#include "measure.h"
#include "staff.h"
#include "score.h"
#include "chord.h"
#include "measurebase.h"
#include "note.h"
#include "layoutbreak.h"
#include "image.h"
#include "score.h"
#include "segment.h"
#include "staff.h"
#include "stafftypechange.h"
#include "system.h"
#include "tempo.h"
#include "xml.h"
#include "system.h"
#include "stafftypechange.h"

namespace Ms {

Expand Down Expand Up @@ -303,16 +301,14 @@ void MeasureBase::layout()
qreal _spatium = spatium();
qreal x;
qreal y;
if (toLayoutBreak(element)->isNoBreak()) {
x = width() - element->width() * .5;
y = -(_spatium + element->height());
}
if (toLayoutBreak(element)->isNoBreak())
x = width() + score()->styleP(Sid::barWidth) - element->width() * .5;
else {
x = -_spatium - element->width() + width()
- breakCount * (element->width() + _spatium * .8);
y = -2 * _spatium - element->height();
x = width() + score()->styleP(Sid::barWidth) - element->width()
- breakCount * (element->width() + _spatium * .5);
breakCount++;
}
y = -2.5 * _spatium - element->height();
element->setPos(x, y);
}
else if (element->isMarker() || element->isJump())
Expand Down
4 changes: 4 additions & 0 deletions libmscore/measurebase.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class MeasureBase : public Element {
Fraction _tick { Fraction(0, 1) };
int _no { 0 }; ///< Measure number, counting from zero
int _noOffset { 0 }; ///< Offset to measure number
qreal _oldWidth { 0 }; ///< Used to restore layout during recalculations in Score::collectSystem()

protected:
Fraction _len { Fraction(0, 1) }; ///< actual length of measure
Expand Down Expand Up @@ -177,6 +178,9 @@ class MeasureBase : public Element {

int index() const;
int measureIndex() const;

void setOldWidth(qreal n) { _oldWidth = n; }
qreal oldWidth() const { return _oldWidth; }
};


Expand Down
87 changes: 45 additions & 42 deletions mscore/debugger/debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,57 +18,55 @@
//=============================================================================

#include "debugger.h"
#include "musescore.h"
//#include "globals.h"
#include "icons.h"
#include "globals.h"
#include "libmscore/element.h"
#include "libmscore/page.h"
#include "libmscore/segment.h"
#include "libmscore/score.h"
#include "libmscore/rest.h"
#include "libmscore/note.h"
#include "libmscore/chord.h"
#include "libmscore/measure.h"
#include "libmscore/text.h"
#include "libmscore/hairpin.h"
#include "libmscore/beam.h"
#include "libmscore/tuplet.h"
#include "libmscore/clef.h"
#include "libmscore/barline.h"
#include "libmscore/hook.h"
#include "libmscore/dynamic.h"
#include "libmscore/slur.h"
#include "libmscore/tie.h"
#include "libmscore/lyrics.h"
#include "libmscore/volta.h"
#include "libmscore/line.h"
#include "libmscore/textline.h"
#include "libmscore/system.h"
#include "musescore.h"

#include "libmscore/accidental.h"
#include "libmscore/arpeggio.h"
#include "libmscore/tremolo.h"
#include "libmscore/articulation.h"
#include "libmscore/ottava.h"
#include "libmscore/bend.h"
#include "libmscore/stem.h"
#include "libmscore/iname.h"
#include "libmscore/accidental.h"
#include "libmscore/keysig.h"
#include "libmscore/sig.h"
#include "libmscore/notedot.h"
#include "libmscore/spacer.h"
#include "libmscore/barline.h"
#include "libmscore/beam.h"
#include "libmscore/box.h"
#include "libmscore/bracket.h"
#include "libmscore/chord.h"
#include "libmscore/chordlist.h"
#include "libmscore/clef.h"
#include "libmscore/dynamic.h"
#include "libmscore/element.h"
#include "libmscore/fret.h"
#include "libmscore/hairpin.h"
#include "libmscore/harmony.h"
#include "libmscore/stemslash.h"
#include "libmscore/hook.h"
#include "libmscore/iname.h"
#include "libmscore/keysig.h"
#include "libmscore/ledgerline.h"
#include "libmscore/line.h"
#include "libmscore/lyrics.h"
#include "libmscore/measure.h"
#include "libmscore/measurenumber.h"
#include "libmscore/note.h"
#include "libmscore/notedot.h"
#include "libmscore/page.h"
#include "libmscore/pitchspelling.h"
#include "libmscore/chordlist.h"
#include "libmscore/bracket.h"
#include "libmscore/bracketItem.h"
#include "libmscore/trill.h"
#include "libmscore/timesig.h"
#include "libmscore/rest.h"
#include "libmscore/score.h"
#include "libmscore/segment.h"
#include "libmscore/sig.h"
#include "libmscore/slur.h"
#include "libmscore/stem.h"
#include "libmscore/stemslash.h"
#include "libmscore/spacer.h"
#include "libmscore/system.h"
#include "libmscore/systemdivider.h"
#include "libmscore/measurenumber.h"
#include "libmscore/text.h"
#include "libmscore/textline.h"
#include "libmscore/tie.h"
#include "libmscore/timesig.h"
#include "libmscore/tremolo.h"
#include "libmscore/trill.h"
#include "libmscore/tuplet.h"
#include "libmscore/volta.h"

namespace Ms {

Expand Down Expand Up @@ -811,6 +809,7 @@ void MeasureView::setElement(Element* e)
mb.repeatCount->setValue(m->repeatCount());
mb.breakMultiMeasureRest->setChecked(m->breakMultiMeasureRest());
mb.mmRestCount->setValue(m->mmRestCount());
mb.oldWidth->setValue(m->oldWidth());
mb.timesig->setText(m->timesig().print());
mb.len->setText(m->ticks().print());
mb.tick->setValue(m->tick().ticks());
Expand Down Expand Up @@ -1789,7 +1788,11 @@ QSize DoubleLabel::sizeHint() const
QFontMetrics fm = fontMetrics();
int h = fm.height() + 4;
int n = 3 + 3;
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
int w = fm.horizontalAdvance(QString("-0.")) + fm.horizontalAdvance('0') * n + 6;
#else
int w = fm.width(QString("-0.")) + fm.width('0') * n + 6;
#endif
return QSize(w, h);
}

Expand Down
Loading

0 comments on commit fa50d4c

Please sign in to comment.