Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #3048 from lasconic/fix-99146-21
fix #99146: File > Save Selection… leads to corrupt score if selectio…
  • Loading branch information
lasconic committed Mar 9, 2017
2 parents 48b2939 + 0299f2d commit a062dec
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 13 deletions.
2 changes: 1 addition & 1 deletion libmscore/box.h
Expand Up @@ -58,7 +58,7 @@ class Box : public MeasureBase {
virtual int grips() const override { return 1; }
virtual void layout() override;
virtual void write(Xml&) const override;
virtual void write(Xml& xml, int, bool) const override { write(xml); }
virtual void write(Xml& xml, int, bool, bool) const override { write(xml); }
virtual void writeProperties(Xml&) const override;
virtual bool readProperties(XmlReader&) override;
virtual void read(XmlReader&) override;
Expand Down
4 changes: 2 additions & 2 deletions libmscore/measure.cpp
Expand Up @@ -1698,7 +1698,7 @@ void Measure::adjustToLen(Fraction nf)
// write
//---------------------------------------------------------

void Measure::write(Xml& xml, int staff, bool writeSystemElements) const
void Measure::write(Xml& xml, int staff, bool writeSystemElements, bool forceTimeSig) const
{
int mno = _no + 1;
if (_len != _timesig) {
Expand Down Expand Up @@ -1752,7 +1752,7 @@ void Measure::write(Xml& xml, int staff, bool writeSystemElements) const
}
Q_ASSERT(first());
Q_ASSERT(last());
score()->writeSegments(xml, strack, etrack, first(), last()->next1(), writeSystemElements, false, false);
score()->writeSegments(xml, strack, etrack, first(), last()->next1(), writeSystemElements, false, false, forceTimeSig);
xml.etag();
}

Expand Down
2 changes: 1 addition & 1 deletion libmscore/measure.h
Expand Up @@ -169,7 +169,7 @@ class Measure : public MeasureBase {
void read(XmlReader&, int idx);
void read(XmlReader& d) { read(d, 0); }
virtual void write(Xml& xml) const override { Element::write(xml); }
void write(Xml&, int, bool writeSystemElements) const;
void write(Xml&, int, bool writeSystemElements, bool forceTimeSig) const;
void writeBox(Xml&) const;
void readBox(XmlReader&);
virtual bool isEditable() const override { return false; }
Expand Down
2 changes: 1 addition & 1 deletion libmscore/measurebase.h
Expand Up @@ -85,7 +85,7 @@ class MeasureBase : public Element {

virtual int ticks() const { return 0; }
virtual void write(Xml&) const override = 0;
virtual void write(Xml&, int, bool) const = 0;
virtual void write(Xml&, int, bool, bool) const = 0;

virtual void layout();

Expand Down
2 changes: 1 addition & 1 deletion libmscore/score.h
Expand Up @@ -961,7 +961,7 @@ class Score : public QObject, public ScoreElement {
void createRevision();
QByteArray readCompressedToBuffer();
QByteArray readToBuffer();
void writeSegments(Xml& xml, int strack, int etrack, Segment* first, Segment* last, bool, bool, bool);
void writeSegments(Xml& xml, int strack, int etrack, Segment* first, Segment* last, bool, bool, bool, bool);

const QMap<QString, QString>& metaTags() const { return _metaTags; }
QMap<QString, QString>& metaTags() { return _metaTags; }
Expand Down
55 changes: 49 additions & 6 deletions libmscore/scorefile.cpp
Expand Up @@ -59,7 +59,7 @@ namespace Ms {
// writeMeasure
//---------------------------------------------------------

static void writeMeasure(Xml& xml, MeasureBase* m, int staffIdx, bool writeSystemElements)
static void writeMeasure(Xml& xml, MeasureBase* m, int staffIdx, bool writeSystemElements, bool forceTimeSig)
{
//
// special case multi measure rest
Expand All @@ -73,10 +73,10 @@ static void writeMeasure(Xml& xml, MeasureBase* m, int staffIdx, bool writeSyste
}

if (m->type() == Element::Type::MEASURE || staffIdx == 0)
m->write(xml, staffIdx, writeSystemElements);
m->write(xml, staffIdx, writeSystemElements, forceTimeSig);

if (mm && mm->mmRest()) {
mm->mmRest()->write(xml, staffIdx, writeSystemElements);
mm->mmRest()->write(xml, staffIdx, writeSystemElements, forceTimeSig);
xml.tag("tick", mm->tick() + mm->ticks()); // rewind tick
}

Expand Down Expand Up @@ -221,8 +221,20 @@ bool Score::write(Xml& xml, bool selectionOnly)
xml.tickDiff = xml.curTick;
xml.curTrack = staffIdx * VOICES;
bool writeSystemElements = staffIdx == staffStart;
for (MeasureBase* m = measureStart; m != measureEnd; m = m->next())
writeMeasure(xml, m, staffIdx, writeSystemElements);
bool firstMeasureWritten = false;
bool forceTimeSig = false;
for (MeasureBase* m = measureStart; m != measureEnd; m = m->next()) {
// force timesig if first measure and selectionOnly
if (selectionOnly && m->isMeasure()) {
if (!firstMeasureWritten) {
forceTimeSig = true;
firstMeasureWritten = true;
}
else
forceTimeSig = false;
}
writeMeasure(xml, m, staffIdx, writeSystemElements, forceTimeSig);
}
xml.etag();
}
}
Expand Down Expand Up @@ -1358,7 +1370,7 @@ qDebug("createRevision");
//---------------------------------------------------------

void Score::writeSegments(Xml& xml, int strack, int etrack,
Segment* fs, Segment* ls, bool writeSystemElements, bool clip, bool needFirstTick)
Segment* fs, Segment* ls, bool writeSystemElements, bool clip, bool needFirstTick, bool forceTimeSig)
{
int endTick = ls == 0 ? lastMeasure()->endTick() : ls->tick();
// in clipboard mode, ls might be in an mmrest
Expand All @@ -1383,7 +1395,12 @@ void Score::writeSegments(Xml& xml, int strack, int etrack,
for (int track = strack; track < etrack; ++track) {
if (!xml.canWriteVoice(track))
continue;

bool firstTickWritten = false;
bool timeSigWritten = false; // for forceTimeSig
bool crWritten = false; // for forceTimeSig
bool keySigWritten = false; // for forceTimeSig

for (Segment* segment = fs; segment && segment != ls; segment = segment->next1()) {
if (track == 0)
segment->setWritten(false);
Expand Down Expand Up @@ -1481,6 +1498,24 @@ void Score::writeSegments(Xml& xml, int strack, int etrack,
#endif
continue;
}
if (forceTimeSig && track2voice(track) == 0 && segment->segmentType() == Segment::Type::ChordRest && !timeSigWritten && !crWritten) {
// we will miss a key sig!
if (!keySigWritten) {
Key k = score()->staff(track2staff(track))->key(segment->tick());
KeySig* ks = new KeySig(this);
ks->setKey(k);
ks->write(xml);
delete ks;
keySigWritten = true;
}
// we will miss a time sig!
Fraction tsf = sigmap()->timesig(segment->tick()).timesig();
TimeSig* ts = new TimeSig(this);
ts->setSig(tsf);
ts->write(xml);
delete ts;
timeSigWritten = true;
}
if (needTick) {
xml.tag("tick", segment->tick() - xml.tickDiff);
xml.curTick = segment->tick();
Expand All @@ -1499,6 +1534,14 @@ void Score::writeSegments(Xml& xml, int strack, int etrack,
}
e->write(xml);
segment->write(xml); // write only once
if (forceTimeSig) {
if (segment->segmentType() == Segment::Type::KeySig)
keySigWritten = true;
if (segment->segmentType() == Segment::Type::TimeSig)
timeSigWritten = true;
if (segment->segmentType() == Segment::Type::ChordRest)
crWritten = true;
}
}
//write spanner ending after the last segment, on the last tick
if (clip || ls == 0) {
Expand Down
2 changes: 1 addition & 1 deletion libmscore/select.cpp
Expand Up @@ -703,7 +703,7 @@ QByteArray Selection::staffMimeData() const
xml.tag(QString("voice id=\"%1\"").arg(voice), offset);
}
}
score()->writeSegments(xml, startTrack, endTrack, seg1, seg2, false, true, true);
score()->writeSegments(xml, startTrack, endTrack, seg1, seg2, false, true, true, false);
xml.etag();
}

Expand Down

0 comments on commit a062dec

Please sign in to comment.