339 lines
10 KiB
C++
339 lines
10 KiB
C++
//=============================================================================
|
|
// 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(s)
|
|
{
|
|
_markerType = Type::FINE;
|
|
setFlags(ElementFlag::MOVABLE | ElementFlag::SELECTABLE | ElementFlag::ON_STAFF);
|
|
setTextStyleType(TextStyleType::REPEAT_LEFT);
|
|
setLayoutToParentWidth(true);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setMarkerType
|
|
//---------------------------------------------------------
|
|
|
|
void Marker::setMarkerType(Type t)
|
|
{
|
|
_markerType = t;
|
|
const char* txt = 0;
|
|
switch (t) {
|
|
case Type::SEGNO:
|
|
txt = "<sym>segno</sym>";
|
|
setLabel("segno");
|
|
break;
|
|
|
|
case Type::VARSEGNO:
|
|
txt = "<sym>segnoSerpent1</sym>";
|
|
setLabel("varsegno");
|
|
break;
|
|
|
|
case Type::CODA:
|
|
txt = "<sym>coda</sym>";
|
|
setLabel("codab");
|
|
break;
|
|
|
|
case Type::VARCODA:
|
|
txt = "<sym>codaSquare</sym>";
|
|
setLabel("varcoda");
|
|
break;
|
|
|
|
case Type::CODETTA:
|
|
txt = "<sym>coda</sym><sym>coda</sym>";
|
|
setLabel("codetta");
|
|
break;
|
|
|
|
case Type::FINE:
|
|
txt = "Fine";
|
|
setTextStyleType(TextStyleType::REPEAT_RIGHT);
|
|
setLabel("fine");
|
|
break;
|
|
|
|
case Type::TOCODA:
|
|
txt = "To Coda";
|
|
setTextStyleType(TextStyleType::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<int>(_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() & AlignmentFlags::HMASK) == 0) // AlignmentFlags::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(textStyle().offset(spatium()));
|
|
Text::layout1();
|
|
// although normally laid out to parent (measure) width,
|
|
// force to center over barline if left-aligned
|
|
if (layoutToParentWidth() && !(textStyle().align() & (AlignmentFlags::RIGHT|AlignmentFlags::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();
|
|
}
|
|
// REPEAT is obsolete, but was previously used for both left and right aligned text
|
|
if (textStyleType() == TextStyleType::REPEAT)
|
|
setTextStyleType(TextStyleType::REPEAT_LEFT);
|
|
setMarkerType(mt);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// write
|
|
//---------------------------------------------------------
|
|
|
|
void Marker::write(Xml& xml) const
|
|
{
|
|
xml.stag(name());
|
|
Text::writeProperties(xml);
|
|
xml.tag("label", _label);
|
|
xml.etag();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// undoSetLabel
|
|
//---------------------------------------------------------
|
|
|
|
void Marker::undoSetLabel(const QString& s)
|
|
{
|
|
score()->undoChangeProperty(this, P_ID::LABEL, s);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// undoSetMarkerType
|
|
//---------------------------------------------------------
|
|
|
|
void Marker::undoSetMarkerType(Type t)
|
|
{
|
|
score()->undoChangeProperty(this, 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());
|
|
}
|
|
|
|
}
|
|
|