Merge pull request #18038 from cbjeukendrup/crash_musicxml_export_after_toggle_mmrest

Fix crash when exporting to MusicXML after toggling MMRests
This commit is contained in:
RomanPudashkin 2023-06-21 17:48:28 +03:00 committed by GitHub
commit 92c12fb2f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 47 additions and 39 deletions

View file

@ -2737,7 +2737,7 @@ EngravingItem* Score::move(const String& cmd)
}
if (ftm) {
if (score()->styleB(Sid::createMultiMeasureRests) && ftm->hasMMRest()) {
ftm = ftm->mmRest1();
ftm = ftm->coveringMMRestOrThis();
}
el = !cr ? ftm->first()->nextChordRest(0, false) : ftm->first()->nextChordRest(trackZeroVoice(cr->track()), false);
}

View file

@ -1051,9 +1051,9 @@ PointF SLine::linePos(Grip grip, System** sys) const
}
}
}
if (score()->styleB(Sid::createMultiMeasureRests)) {
m = m->mmRest1();
}
m = m->coveringMMRestOrThis();
assert(m->system());
*sys = m->system();
}

View file

@ -2729,27 +2729,36 @@ Measure* Measure::mmRestLast() const
}
//---------------------------------------------------------
// mmRest1
// return the multi measure rest this measure is covered
// by
// coveringMMRestOrThis
// if multi-measure rests are enabled,
// and this measure is covered by an MMRest,
// return that MMRest.
// otherwise, return the measure itself.
//---------------------------------------------------------
const Measure* Measure::mmRest1() const
const Measure* Measure::coveringMMRestOrThis() const
{
if (!score()->styleB(Sid::createMultiMeasureRests)) {
return this;
}
if (m_mmRest) {
return m_mmRest;
}
if (m_mmRestCount != -1) {
// return const_cast<Measure*>(this);
return this;
}
const Measure* m = this;
while (m && !m->m_mmRest) {
m = m->prevMeasure();
}
if (m) {
return const_cast<Measure*>(m->m_mmRest);
return m->m_mmRest;
}
return 0;
}

View file

@ -304,7 +304,7 @@ public:
bool hasMMRest() const { return m_mmRest != 0; }
bool isMMRest() const { return m_mmRestCount > 0; }
Measure* mmRest() const { return m_mmRest; }
const Measure* mmRest1() const;
const Measure* coveringMMRestOrThis() const;
void setMMRest(Measure* m) { m_mmRest = m; }
int mmRestCount() const { return m_mmRestCount; } // number of measures m_mmRest spans
void setMMRestCount(int n) { m_mmRestCount = n; }

View file

@ -566,7 +566,7 @@ MeasureBase* MeasureBase::prevMM() const
if (_prev
&& _prev->isMeasure()
&& score()->styleB(Sid::createMultiMeasureRests)) {
return const_cast<Measure*>(toMeasure(_prev)->mmRest1());
return const_cast<Measure*>(toMeasure(_prev)->coveringMMRestOrThis());
}
return _prev;
}

View file

@ -1948,13 +1948,7 @@ Measure* Score::lastMeasure() const
Measure* Score::lastMeasureMM() const
{
Measure* m = lastMeasure();
if (m && styleB(Sid::createMultiMeasureRests)) {
Measure* m1 = const_cast<Measure*>(toMeasure(m->mmRest1()));
if (m1) {
return m1;
}
}
return m;
return m ? const_cast<Measure*>(m->coveringMMRestOrThis()) : nullptr;
}
//---------------------------------------------------------
@ -4633,7 +4627,7 @@ ChordRest* Score::cmdNextPrevSystem(ChordRest* cr, bool next)
{
auto newCR = cr;
auto currentMeasure = cr->measure();
auto currentSystem = currentMeasure->system() ? currentMeasure->system() : currentMeasure->mmRest1()->system();
auto currentSystem = currentMeasure->system() ? currentMeasure->system() : currentMeasure->coveringMMRestOrThis()->system();
if (!currentSystem) {
return cr;
}
@ -4644,7 +4638,9 @@ ChordRest* Score::cmdNextPrevSystem(ChordRest* cr, bool next)
if (next) {
if ((destinationMeasure = currentSystem->lastMeasure()->nextMeasure())) {
// There is a next system present: get it and accommodate for MMRest
currentSystem = destinationMeasure->system() ? destinationMeasure->system() : destinationMeasure->mmRest1()->system();
currentSystem = destinationMeasure->system()
? destinationMeasure->system()
: destinationMeasure->coveringMMRestOrThis()->system();
if ((destinationMeasure = currentSystem->firstMeasure())) {
if ((newCR = destinationMeasure->first()->nextChordRest(trackZeroVoice(cr->track()), false))) {
cr = newCR;
@ -4678,7 +4674,9 @@ ChordRest* Score::cmdNextPrevSystem(ChordRest* cr, bool next)
return cr;
}
}
if (!(currentSystem = destinationMeasure->system() ? destinationMeasure->system() : destinationMeasure->mmRest1()->system())) {
if (!(currentSystem = destinationMeasure->system()
? destinationMeasure->system()
: destinationMeasure->coveringMMRestOrThis()->system())) {
return cr;
}
destinationMeasure = currentSystem->firstMeasure();
@ -4814,7 +4812,7 @@ EngravingItem* Score::getScoreElementOfMeasureBase(MeasureBase* mb) const
} else if ((currentMeasure = mb->findMeasure())) {
// Accommodate for MMRest
if (score()->styleB(Sid::createMultiMeasureRests) && currentMeasure->hasMMRest()) {
currentMeasure = currentMeasure->mmRest1();
currentMeasure = currentMeasure->coveringMMRestOrThis();
}
if ((cr = currentMeasure->first()->nextChordRest(0, false))) {
el = cr;
@ -4876,7 +4874,7 @@ ChordRest* Score::cmdTopStaff(ChordRest* cr)
if (destinationMeasure) {
// Accommodate for MMRest
if (score()->styleB(Sid::createMultiMeasureRests) && destinationMeasure->hasMMRest()) {
destinationMeasure = destinationMeasure->mmRest1();
destinationMeasure = destinationMeasure->coveringMMRestOrThis();
}
// Get first ChordRest of top staff
cr = destinationMeasure->first()->nextChordRest(0, false);

View file

@ -173,7 +173,7 @@ EngravingObject* Measure::scanParent() const
if (isMMRest()) { // this is MMR
return system();
} else if (m_mmRestCount < 0) { // this is part of MMR
return const_cast<Measure*>(mmRest1());
return const_cast<Measure*>(coveringMMRestOrThis());
}
// for a normal measure
return system();

View file

@ -559,7 +559,7 @@ void Selection::updateSelectedElements()
return;
}
if (s2 && s2 == s2->measure()->first() && !(s2->measure()->prevMeasure() && s2->measure()->prevMeasure()->mmRest1())) {
if (s2 && s2 == s2->measure()->first() && !(s2->measure()->prevMeasure() && s2->measure()->prevMeasure()->coveringMMRestOrThis())) {
// we want the last segment of the previous measure (unless it's part of a MMrest)
s2 = s2->prev1();
}

View file

@ -1939,7 +1939,7 @@ static void writeBarlineFermata(const BarLine* const barline, XmlWriter& xml, co
void ExportMusicXml::barlineRight(const Measure* const m, const track_idx_t strack, const track_idx_t etrack)
{
const Measure* mmR1 = m->mmRest1(); // the multi measure rest this measure is covered by
const Measure* mmR1 = m->coveringMMRestOrThis(); // the multi measure rest this measure is covered by
const Measure* mmRLst = mmR1->isMMRest() ? mmR1->mmRestLast() : 0; // last measure of replaced sequence of empty measures
// note: use barlinetype as found in multi measure rest for last measure of replaced sequence
BarLineType bst = m == mmRLst ? mmR1->endBarLineType() : m->endBarLineType();
@ -5588,7 +5588,7 @@ static void measureRepeat(XmlWriter& xml, Attributes& attr, const Measure* const
static void measureStyle(XmlWriter& xml, Attributes& attr, const Measure* const m, const int partIndex)
{
const Measure* mmR1 = m->mmRest1();
const Measure* mmR1 = m->coveringMMRestOrThis();
if (m != mmR1 && m == mmR1->mmRestFirst()) {
attr.doAttr(xml, true);
xml.startElement("measure-style");
@ -6376,7 +6376,7 @@ void ExportMusicXml::print(const Measure* const m, const int partNr, const int f
// in the replacing measure
// note: for a normal measure, mmRest1 is the measure itself,
// for a multi-measure rest, it is the replacing measure
const Measure* mmR1 = m->mmRest1();
const Measure* mmR1 = m->coveringMMRestOrThis();
const System* system = mmR1->system();
// Put the system print suggestions only for the first part in a score...
@ -7008,7 +7008,7 @@ static System* findLastSystemWithMeasures(const Page* const page)
static bool isFirstMeasureInSystem(const Measure* const measure)
{
const auto system = measure->mmRest1()->system();
const auto system = measure->coveringMMRestOrThis()->system();
const auto firstMeasureInSystem = system->firstMeasure();
const auto realFirstMeasureInSystem = firstMeasureInSystem->isMMRest() ? firstMeasureInSystem->mmRestFirst() : firstMeasureInSystem;
return measure == realFirstMeasureInSystem;
@ -7020,7 +7020,7 @@ static bool isFirstMeasureInSystem(const Measure* const measure)
static bool isFirstMeasureInLastSystem(const Measure* const measure)
{
const auto system = measure->mmRest1()->system();
const auto system = measure->coveringMMRestOrThis()->system();
const auto page = system->page();
/*
@ -7057,7 +7057,7 @@ static bool systemHasMeasures(const System* const system)
static std::vector<TBox*> findTextFramesToWriteAsWordsAbove(const Measure* const measure)
{
const auto system = measure->mmRest1()->system();
const auto system = measure->coveringMMRestOrThis()->system();
const auto page = system->page();
const size_t systemIndex = mu::indexOf(page->systems(), system);
std::vector<TBox*> tboxes;
@ -7081,7 +7081,7 @@ static std::vector<TBox*> findTextFramesToWriteAsWordsAbove(const Measure* const
static std::vector<TBox*> findTextFramesToWriteAsWordsBelow(const Measure* const measure)
{
const auto system = measure->mmRest1()->system();
const auto system = measure->coveringMMRestOrThis()->system();
const auto page = system->page();
const size_t systemIndex = static_cast<int>(mu::indexOf(page->systems(), system));
std::vector<TBox*> tboxes;
@ -7147,15 +7147,16 @@ void ExportMusicXml::writeMeasureTracks(const Measure* const m,
for (const auto tbox : tboxesAbove) {
// note: use mmRest1() to get at a possible multi-measure rest,
// as the covered measure would be positioned at 0,0.
tboxTextAsWords(tbox->text(), 0, mu::PointF(tbox->text()->canvasPos() - m->mmRest1()->canvasPos()).toQPointF());
tboxTextAsWords(tbox->text(), 0, mu::PointF(
tbox->text()->canvasPos() - m->coveringMMRestOrThis()->canvasPos()).toQPointF());
}
_tboxesAboveWritten = true;
}
if (!_tboxesBelowWritten && isLastPart && isLastStaffOfPart) {
for (const auto tbox : tboxesBelow) {
const auto lastStaffNr = track2staff(track);
const auto sys = m->mmRest1()->system();
auto textPos = tbox->text()->canvasPos() - m->mmRest1()->canvasPos();
const auto sys = m->coveringMMRestOrThis()->system();
auto textPos = tbox->text()->canvasPos() - m->coveringMMRestOrThis()->canvasPos();
if (lastStaffNr < sys->staves().size()) {
// convert to position relative to last staff of system
textPos.setY(textPos.y() - (sys->staffCanvasYpage(lastStaffNr) - sys->staffCanvasYpage(0)));

View file

@ -2637,7 +2637,7 @@ void NotationInteraction::selectEmptyTrailingMeasure()
}
if (ftm) {
if (score()->styleB(mu::engraving::Sid::createMultiMeasureRests) && ftm->hasMMRest()) {
ftm = ftm->mmRest1();
ftm = ftm->coveringMMRestOrThis();
}
EngravingItem* el
= !cr ? ftm->first()->nextChordRest(0, false) : ftm->first()->nextChordRest(mu::engraving::trackZeroVoice(cr->track()), false);

View file

@ -173,7 +173,7 @@ mu::engraving::Segment* NotationSelectionRange::rangeStartSegment() const
}
if (!startSegment->measure()->system()) {
const Measure* mmr = startSegment->measure()->mmRest1();
const Measure* mmr = startSegment->measure()->coveringMMRestOrThis();
if (!mmr || mmr->system()) {
return nullptr;
}
@ -226,7 +226,7 @@ const
mu::engraving::System* nextSegmentSystem = nextSegment->measure()->system();
if (!nextSegmentSystem) {
const Measure* mmr = nextSegment->measure()->mmRest1();
const Measure* mmr = nextSegment->measure()->coveringMMRestOrThis();
if (mmr) {
nextSegmentSystem = mmr->system();
}