//============================================================================= // MuseScore // Music Composition & Notation // // Copyright (C) 2002-2013 Werner Schweer // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 // as published by the Free Software Foundation and appearing in // the file LICENCE.GPL //============================================================================= #include "marker.h" #include "score.h" #include "sym.h" #include "xml.h" #include "measure.h" namespace Ms { //must be in sync with Marker::Type enum const MarkerTypeItem markerTypeTable[] = { { Marker::Type::SEGNO , QT_TRANSLATE_NOOP("markerType", "Segno") }, { Marker::Type::VARSEGNO, QT_TRANSLATE_NOOP("markerType", "Segno variation")}, { Marker::Type::CODA , QT_TRANSLATE_NOOP("markerType", "Coda") }, { Marker::Type::VARCODA , QT_TRANSLATE_NOOP("markerType", "Varied coda") }, { Marker::Type::CODETTA , QT_TRANSLATE_NOOP("markerType", "Codetta") }, { Marker::Type::FINE , QT_TRANSLATE_NOOP("markerType", "Fine") }, { Marker::Type::TOCODA , QT_TRANSLATE_NOOP("markerType", "To Coda") }, { Marker::Type::USER , QT_TRANSLATE_NOOP("markerType", "Custom") } }; int markerTypeTableSize() { return sizeof(markerTypeTable)/sizeof(MarkerTypeItem) - 1; //-1 for the user defined } //--------------------------------------------------------- // Marker //--------------------------------------------------------- Marker::Marker(Score* s) : Text(SubStyle::REPEAT_LEFT, s) { _markerType = Type::FINE; setFlags(ElementFlag::MOVABLE | ElementFlag::SELECTABLE | ElementFlag::ON_STAFF); setLayoutToParentWidth(true); } //--------------------------------------------------------- // setMarkerType //--------------------------------------------------------- void Marker::setMarkerType(Type t) { _markerType = t; const char* txt = 0; switch (t) { case Type::SEGNO: txt = "segno"; setLabel("segno"); break; case Type::VARSEGNO: txt = "segnoSerpent1"; setLabel("varsegno"); break; case Type::CODA: txt = "coda"; setLabel("codab"); break; case Type::VARCODA: txt = "codaSquare"; setLabel("varcoda"); break; case Type::CODETTA: txt = "codacoda"; setLabel("codetta"); break; case Type::FINE: txt = "Fine"; initSubStyle(SubStyle::REPEAT_RIGHT); setLabel("fine"); break; case Type::TOCODA: txt = "To Coda"; initSubStyle(SubStyle::REPEAT_RIGHT); setLabel("coda"); break; case Type::USER: break; default: qDebug("unknown marker type %d", int(t)); break; } if (empty() && txt) setXmlText(txt); } QString Marker::markerTypeUserName() const { return qApp->translate("markerType", markerTypeTable[static_cast(_markerType)].name.toUtf8().constData()); } //--------------------------------------------------------- // styleChanged //--------------------------------------------------------- void Marker::styleChanged() { setMarkerType(_markerType); } //--------------------------------------------------------- // adjustReadPos //--------------------------------------------------------- void Marker::adjustReadPos() { if (!readPos().isNull()) { QPointF uo; /* if (score()->mscVersion() <= 114) { // rebase from Measure to Segment uo = userOff(); uo.rx() -= segment()->pos().x(); // 1.2 is always HCENTER aligned if ((textStyle().align() & Align::HMASK) == 0) // Align::LEFT uo.rx() -= bbox().width() * .5; } else */ uo = readPos() - ipos(); setUserOff(uo); setReadPos(QPointF()); } } //--------------------------------------------------------- // markerType //--------------------------------------------------------- Marker::Type Marker::markerType(const QString& s) const { if (s == "segno") return Type::SEGNO; else if (s == "varsegno") return Type::VARSEGNO; else if (s == "codab") return Type::CODA; else if (s == "varcoda") return Type::VARCODA; else if (s == "codetta") return Type::CODETTA; else if (s == "fine") return Type::FINE; else if (s == "coda") return Type::TOCODA; else return Type::USER; } //--------------------------------------------------------- // layout //--------------------------------------------------------- void Marker::layout() { setPos(QPointF(0.0, score()->styleP(StyleIdx::markerPosAbove))); Text::layout1(); // although normally laid out to parent (measure) width, // force to center over barline if left-aligned if (layoutToParentWidth() && !(align() & (Align::RIGHT|Align::HCENTER))) rxpos() -= width() * 0.5; adjustReadPos(); } //--------------------------------------------------------- // read //--------------------------------------------------------- void Marker::read(XmlReader& e) { Type mt = Type::SEGNO; while (e.readNextStartElement()) { const QStringRef& tag(e.name()); if (tag == "label") { QString s(e.readElementText()); setLabel(s); mt = markerType(s); } else if (!Text::readProperties(e)) e.unknown(); } setMarkerType(mt); } //--------------------------------------------------------- // write //--------------------------------------------------------- void Marker::write(XmlWriter& xml) const { xml.stag(name()); Text::writeProperties(xml); xml.tag("label", _label); xml.etag(); } //--------------------------------------------------------- // undoSetLabel //--------------------------------------------------------- void Marker::undoSetLabel(const QString& s) { undoChangeProperty(P_ID::LABEL, s); } //--------------------------------------------------------- // undoSetMarkerType //--------------------------------------------------------- void Marker::undoSetMarkerType(Type t) { undoChangeProperty(P_ID::MARKER_TYPE, int(t)); } //--------------------------------------------------------- // getProperty //--------------------------------------------------------- QVariant Marker::getProperty(P_ID propertyId) const { switch (propertyId) { case P_ID::LABEL: return label(); case P_ID::MARKER_TYPE: return int(markerType()); default: break; } return Text::getProperty(propertyId); } //--------------------------------------------------------- // setProperty //--------------------------------------------------------- bool Marker::setProperty(P_ID propertyId, const QVariant& v) { switch (propertyId) { case P_ID::LABEL: setLabel(v.toString()); break; case P_ID::MARKER_TYPE: setMarkerType(Type(v.toInt())); break; default: if (!Text::setProperty(propertyId, v)) return false; break; } score()->setLayoutAll(); return true; } //--------------------------------------------------------- // propertyDefault //--------------------------------------------------------- QVariant Marker::propertyDefault(P_ID propertyId) const { switch (propertyId) { case P_ID::LABEL: return QString(); case P_ID::MARKER_TYPE: return int(Type::FINE); default: break; } return Text::propertyDefault(propertyId); } //--------------------------------------------------------- // nextElement //--------------------------------------------------------- Element* Marker::nextElement() { Segment* seg; if (markerType() == Marker::Type::FINE) { seg = measure()->last(); return seg->firstElement(staffIdx()); } Measure* prevMeasure = measure()->prevMeasureMM(); if (prevMeasure) { seg = prevMeasure->last(); return seg->firstElement(staffIdx()); } return Element::nextElement(); } //--------------------------------------------------------- // prevElement //--------------------------------------------------------- Element* Marker::prevElement() { //it's the same barline return nextElement(); } //--------------------------------------------------------- // accessibleInfo //--------------------------------------------------------- QString Marker::accessibleInfo() const { return QString("%1: %2").arg(Element::accessibleInfo()).arg(markerTypeUserName()); } }