bool ChordRest::readProperties(XmlReader& e) { const QStringRef& tag(e.name()); if (tag == "durationType") { setDurationType(e.readElementText()); if (actualDurationType().type() != TDuration::DurationType::V_MEASURE) { if ((type() == Element::Type::REST) && // for backward compatibility, convert V_WHOLE rests to V_MEASURE // if long enough to fill a measure. // OTOH, freshly created (un-initialized) rests have numerator == 0 (< 4/4) // (see Fraction() constructor in fraction.h; this happens for instance // when pasting selection from clipboard): they should not be converted duration().numerator() != 0 && // rest durations are initialized to full measure duration when // created upon reading the <Rest> tag (see Measure::read() ) // so a V_WHOLE rest in a measure of 4/4 or less => V_MEASURE (actualDurationType()==TDuration::DurationType::V_WHOLE && duration() <= Fraction(4, 4)) ) { // old pre 2.0 scores: convert setDurationType(TDuration::DurationType::V_MEASURE); } else // not from old score: set duration fraction from duration type setDuration(actualDurationType().fraction()); } else { if (score()->mscVersion() < 115) { SigEvent event = score()->sigmap()->timesig(e.tick()); setDuration(event.timesig()); } } } else if (tag == "BeamMode") { QString val(e.readElementText()); Beam::Mode bm = Beam::Mode::AUTO; if (val == "auto") bm = Beam::Mode::AUTO; else if (val == "begin") bm = Beam::Mode::BEGIN; else if (val == "mid") bm = Beam::Mode::MID; else if (val == "end") bm = Beam::Mode::END; else if (val == "no") bm = Beam::Mode::NONE; else if (val == "begin32") bm = Beam::Mode::BEGIN32; else if (val == "begin64") bm = Beam::Mode::BEGIN64; else bm = Beam::Mode(val.toInt()); _beamMode = Beam::Mode(bm); } else if (tag == "Attribute" || tag == "Articulation") { // obsolete: "Attribute" Articulation* atr = new Articulation(score()); atr->read(e); add(atr); } else if (tag == "leadingSpace") { qDebug("ChordRest: leadingSpace obsolete"); // _extraLeadingSpace = Spatium(val.toDouble()); e.skipCurrentElement(); } else if (tag == "trailingSpace") { qDebug("ChordRest: trailingSpace obsolete"); // _extraTrailingSpace = Spatium(val.toDouble()); e.skipCurrentElement(); } else if (tag == "Beam") { int id = e.readInt(); Beam* beam = e.findBeam(id); if (beam) beam->add(this); // also calls this->setBeam(beam) else qDebug("Beam id %d not found", id); } else if (tag == "small") _small = e.readInt(); else if (tag == "duration") setDuration(e.readFraction()); else if (tag == "ticklen") { // obsolete (version < 1.12) int mticks = score()->sigmap()->timesig(e.tick()).timesig().ticks(); int i = e.readInt(); if (i == 0) i = mticks; if ((type() == Element::Type::REST) && (mticks == i)) { setDurationType(TDuration::DurationType::V_MEASURE); setDuration(Fraction::fromTicks(i)); } else { Fraction f = Fraction::fromTicks(i); setDuration(f); setDurationType(TDuration(f)); } } else if (tag == "dots") setDots(e.readInt()); else if (tag == "move") _staffMove = e.readInt(); else if (tag == "Slur") { int id = e.intAttribute("id"); if (id == 0) id = e.intAttribute("number"); // obsolete Spanner* spanner = e.findSpanner(id); if (!spanner) qDebug("ChordRest::read(): Slur id %d not found", id); else { QString atype(e.attribute("type")); if (atype == "start") { spanner->setTick(e.tick()); if (spanner->ticks() > 0) // stop has been read first, ticks is tick2 - (-1) spanner->setTick2(spanner->ticks() - 1); spanner->setTrack(track()); if (spanner->type() == Element::Type::SLUR) spanner->setStartElement(this); if (e.pasteMode()) { for (Element* e : spanner->linkList()) { if (e == spanner) continue; Spanner* ls = static_cast<Spanner*>(e); ls->setTick(spanner->tick()); for (Element* ee : linkList()) { ChordRest* cr = static_cast<ChordRest*>(ee); if (cr->score() == ee->score() && cr->staffIdx() == ls->staffIdx()) { ls->setTrack(cr->track()); if (ls->type() == Element::Type::SLUR) ls->setStartElement(cr); break; } } } } } else if (atype == "stop") { spanner->setTick2(e.tick()); spanner->setTrack2(track()); if (spanner->type() == Element::Type::SLUR) spanner->setEndElement(this); Chord* start = static_cast<Chord*>(spanner->startElement()); if (start) spanner->setTrack(start->track()); if (e.pasteMode()) { for (Element* e : spanner->linkList()) { if (e == spanner) continue; Spanner* ls = static_cast<Spanner*>(e); ls->setTick2(spanner->tick2()); for (Element* ee : linkList()) { ChordRest* cr = static_cast<ChordRest*>(ee); if (cr->score() == ee->score() && cr->staffIdx() == ls->staffIdx()) { ls->setTrack2(cr->track()); if (ls->type() == Element::Type::SLUR) ls->setEndElement(cr); break; } } } } } else qDebug("ChordRest::read(): unknown Slur type <%s>", qPrintable(atype)); } e.readNext(); } else if (tag == "Lyrics" /*|| tag == "FiguredBass"*/) { Element* element = Element::name2Element(tag, score()); element->setTrack(e.track()); element->read(e); add(element); } else if (tag == "pos") { QPointF pt = e.readPoint(); if (score()->mscVersion() > 114) setUserOff(pt * spatium()); } else if (tag == "offset") { if (score()->mscVersion() > 114) // || voice() >= 2) { DurationElement::readProperties(e); else if (type() == Element::Type::REST) { DurationElement::readProperties(e); setUserXoffset(0.0); // honor Y offset but not X for rests in older scores } else e.skipCurrentElement(); // ignore manual layout otherwise } else if (DurationElement::readProperties(e)) return true; else return false; return true; }
void ChordRest::writeProperties(Xml& xml) const { DurationElement::writeProperties(xml); // // Beam::Mode default: // REST - Beam::Mode::NONE // CHORD - Beam::Mode::AUTO // if ((type() == Element::Type::REST && _beamMode != Beam::Mode::NONE) || (type() == Element::Type::CHORD && _beamMode != Beam::Mode::AUTO)) { QString s; switch(_beamMode) { case Beam::Mode::AUTO: s = "auto"; break; case Beam::Mode::BEGIN: s = "begin"; break; case Beam::Mode::MID: s = "mid"; break; case Beam::Mode::END: s = "end"; break; case Beam::Mode::NONE: s = "no"; break; case Beam::Mode::BEGIN32: s = "begin32"; break; case Beam::Mode::BEGIN64: s = "begin64"; break; case Beam::Mode::INVALID: s = "?"; break; } xml.tag("BeamMode", s); } writeProperty(xml, P_ID::SMALL); if (actualDurationType().dots()) xml.tag("dots", actualDurationType().dots()); writeProperty(xml, P_ID::STAFF_MOVE); if (actualDurationType().isValid()) xml.tag("durationType", actualDurationType().name()); if (!duration().isZero() && (!actualDurationType().fraction().isValid() || (actualDurationType().fraction() != duration()))) xml.fTag("duration", duration()); foreach(const Articulation* a, _articulations) a->write(xml); #ifndef NDEBUG if (_beam && (MScore::testMode || !_beam->generated())) xml.tag("Beam", _beam->id()); #else if (_beam && !_beam->generated()) xml.tag("Beam", _beam->id()); #endif foreach(Lyrics* lyrics, _lyricsList) { if (lyrics) lyrics->write(xml); } if (!isGrace()) { Fraction t(globalDuration()); if (staff()) t *= staff()->timeStretch(xml.curTick); xml.curTick += t.ticks(); } for (auto i : score()->spanner()) { // TODO: dont search whole list Spanner* s = i.second; if (s->generated() || s->type() != Element::Type::SLUR || !xml.canWrite(s)) continue; if (s->startElement() == this) { int id = xml.spannerId(s); xml.tagE(QString("Slur type=\"start\" id=\"%1\"").arg(id)); } else if (s->endElement() == this) { int id = xml.spannerId(s); xml.tagE(QString("Slur type=\"stop\" id=\"%1\"").arg(id)); } } }