1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2002-2013 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "marker.h"
14 #include "score.h"
15 #include "sym.h"
16 #include "xml.h"
17 #include "measure.h"
18
19 namespace Ms {
20
21 //---------------------------------------------------------
22 // markerStyle
23 //---------------------------------------------------------
24
25 static const ElementStyle markerStyle {
26 { Sid::repeatLeftPlacement, Pid::PLACEMENT },
27 { Sid::repeatMinDistance, Pid::MIN_DISTANCE },
28 };
29
30 //must be in sync with Marker::Type enum
31 const MarkerTypeItem markerTypeTable[] = {
32 { Marker::Type::SEGNO , QT_TRANSLATE_NOOP("markerType", "Segno") },
33 { Marker::Type::VARSEGNO , QT_TRANSLATE_NOOP("markerType", "Segno variation") },
34 { Marker::Type::CODA , QT_TRANSLATE_NOOP("markerType", "Coda") },
35 { Marker::Type::VARCODA , QT_TRANSLATE_NOOP("markerType", "Varied coda") },
36 { Marker::Type::CODETTA , QT_TRANSLATE_NOOP("markerType", "Codetta") },
37 { Marker::Type::FINE , QT_TRANSLATE_NOOP("markerType", "Fine") },
38 { Marker::Type::TOCODA , QT_TRANSLATE_NOOP("markerType", "To Coda") },
39 { Marker::Type::TOCODASYM, QT_TRANSLATE_NOOP("markerType", "To Coda (Symbol)")},
40 { Marker::Type::USER , QT_TRANSLATE_NOOP("markerType", "Custom") }
41 };
42
markerTypeTableSize()43 int markerTypeTableSize()
44 {
45 return sizeof(markerTypeTable)/sizeof(MarkerTypeItem) - 1; //-1 for the user defined
46 }
47
48 //---------------------------------------------------------
49 // Marker
50 //---------------------------------------------------------
51
Marker(Score * s)52 Marker::Marker(Score* s)
53 : Marker(s, Tid::REPEAT_LEFT)
54 {
55 }
56
Marker(Score * s,Tid tid)57 Marker::Marker(Score* s, Tid tid)
58 : TextBase(s, tid, ElementFlag::MOVABLE | ElementFlag::ON_STAFF | ElementFlag::SYSTEM)
59 {
60 initElementStyle(&markerStyle);
61 _markerType = Type::FINE;
62 setLayoutToParentWidth(true);
63 }
64
65 //---------------------------------------------------------
66 // setMarkerType
67 //---------------------------------------------------------
68
setMarkerType(Type t)69 void Marker::setMarkerType(Type t)
70 {
71 _markerType = t;
72 const char* txt = 0;
73 switch (t) {
74 case Type::SEGNO:
75 txt = "<sym>segno</sym>";
76 setLabel("segno");
77 break;
78
79 case Type::VARSEGNO:
80 txt = "<sym>segnoSerpent1</sym>";
81 setLabel("varsegno");
82 break;
83
84 case Type::CODA:
85 txt = "<sym>coda</sym>";
86 setLabel("codab");
87 break;
88
89 case Type::VARCODA:
90 txt = "<sym>codaSquare</sym>";
91 setLabel("varcoda");
92 break;
93
94 case Type::CODETTA:
95 txt = "<sym>coda</sym><sym>coda</sym>";
96 setLabel("codetta");
97 break;
98
99 case Type::FINE:
100 txt = "Fine";
101 initTid(Tid::REPEAT_RIGHT, true);
102 setLabel("fine");
103 break;
104
105 case Type::TOCODA:
106 txt = "To Coda";
107 initTid(Tid::REPEAT_RIGHT, true);
108 setLabel("coda");
109 break;
110
111 case Type::TOCODASYM:
112 txt = "To <font size=\"20\"/><sym>coda</sym>";
113 initTid(Tid::REPEAT_RIGHT, true);
114 setLabel("coda");
115 break;
116
117 case Type::USER:
118 break;
119
120 default:
121 qDebug("unknown marker type %d", int(t));
122 break;
123 }
124 if (empty() && txt)
125 setXmlText(txt);
126 }
127
128 //---------------------------------------------------------
129 // markerTypeUserName
130 //---------------------------------------------------------
131
markerTypeUserName() const132 QString Marker::markerTypeUserName() const
133 {
134 return qApp->translate("markerType", markerTypeTable[static_cast<int>(_markerType)].name.toUtf8().constData());
135 }
136
137 //---------------------------------------------------------
138 // styleChanged
139 //---------------------------------------------------------
140
styleChanged()141 void Marker::styleChanged()
142 {
143 setMarkerType(_markerType);
144 TextBase::styleChanged();
145 }
146
147 //---------------------------------------------------------
148 // markerType
149 //---------------------------------------------------------
150
markerType(const QString & s) const151 Marker::Type Marker::markerType(const QString& s) const
152 {
153 if (s == "segno")
154 return Type::SEGNO;
155 else if (s == "varsegno")
156 return Type::VARSEGNO;
157 else if (s == "codab")
158 return Type::CODA;
159 else if (s == "varcoda")
160 return Type::VARCODA;
161 else if (s == "codetta")
162 return Type::CODETTA;
163 else if (s == "fine")
164 return Type::FINE;
165 else if (s == "coda")
166 return Type::TOCODA;
167 else
168 return Type::USER;
169 }
170
171 //---------------------------------------------------------
172 // layout
173 //---------------------------------------------------------
174
layout()175 void Marker::layout()
176 {
177 TextBase::layout();
178
179 // although normally laid out to parent (measure) width,
180 // force to center over barline if left-aligned
181
182 if (layoutToParentWidth() && !(align() & (Align::RIGHT | Align::HCENTER)))
183 rxpos() -= width() * 0.5;
184
185 autoplaceMeasureElement();
186 }
187
188 //---------------------------------------------------------
189 // read
190 //---------------------------------------------------------
191
read(XmlReader & e)192 void Marker::read(XmlReader& e)
193 {
194 Type mt = Type::SEGNO;
195
196 while (e.readNextStartElement()) {
197 const QStringRef& tag(e.name());
198 if (tag == "label") {
199 QString s(e.readElementText());
200 setLabel(s);
201 mt = markerType(s);
202 }
203 else if (!TextBase::readProperties(e))
204 e.unknown();
205 }
206 setMarkerType(mt);
207 }
208
209 //---------------------------------------------------------
210 // write
211 //---------------------------------------------------------
212
write(XmlWriter & xml) const213 void Marker::write(XmlWriter& xml) const
214 {
215 xml.stag(this);
216 TextBase::writeProperties(xml);
217 xml.tag("label", _label);
218 xml.etag();
219 }
220
221 //---------------------------------------------------------
222 // undoSetLabel
223 //---------------------------------------------------------
224
undoSetLabel(const QString & s)225 void Marker::undoSetLabel(const QString& s)
226 {
227 undoChangeProperty(Pid::LABEL, s);
228 }
229
230 //---------------------------------------------------------
231 // undoSetMarkerType
232 //---------------------------------------------------------
233
undoSetMarkerType(Type t)234 void Marker::undoSetMarkerType(Type t)
235 {
236 undoChangeProperty(Pid::MARKER_TYPE, int(t));
237 }
238
239 //---------------------------------------------------------
240 // getProperty
241 //---------------------------------------------------------
242
getProperty(Pid propertyId) const243 QVariant Marker::getProperty(Pid propertyId) const
244 {
245 switch (propertyId) {
246 case Pid::LABEL:
247 return label();
248 case Pid::MARKER_TYPE:
249 return int(markerType());
250 default:
251 break;
252 }
253 return TextBase::getProperty(propertyId);
254 }
255
256 //---------------------------------------------------------
257 // setProperty
258 //---------------------------------------------------------
259
setProperty(Pid propertyId,const QVariant & v)260 bool Marker::setProperty(Pid propertyId, const QVariant& v)
261 {
262 switch (propertyId) {
263 case Pid::LABEL:
264 setLabel(v.toString());
265 break;
266 case Pid::MARKER_TYPE:
267 setMarkerType(Type(v.toInt()));
268 break;
269 default:
270 if (!TextBase::setProperty(propertyId, v))
271 return false;
272 break;
273 }
274 triggerLayoutAll();
275 return true;
276 }
277
278 //---------------------------------------------------------
279 // propertyDefault
280 //---------------------------------------------------------
281
propertyDefault(Pid propertyId) const282 QVariant Marker::propertyDefault(Pid propertyId) const
283 {
284 switch (propertyId) {
285 case Pid::LABEL:
286 return QString();
287 case Pid::MARKER_TYPE:
288 return int(Type::FINE);
289 case Pid::PLACEMENT:
290 return int(Placement::ABOVE);
291 default:
292 break;
293 }
294 return TextBase::propertyDefault(propertyId);
295 }
296
297
298 //---------------------------------------------------------
299 // nextSegmentElement
300 //---------------------------------------------------------
301
nextSegmentElement()302 Element* Marker::nextSegmentElement()
303 {
304 Segment* seg;
305 if (markerType() == Marker::Type::FINE) {
306 seg = measure()->last();
307 return seg->firstElement(staffIdx());
308 }
309 Measure* prevMeasure = measure()->prevMeasureMM();
310 if (prevMeasure) {
311 seg = prevMeasure->last();
312 return seg->firstElement(staffIdx());
313 }
314 return Element::nextSegmentElement();
315 }
316
317 //---------------------------------------------------------
318 // prevSegmentElement
319 //---------------------------------------------------------
320
prevSegmentElement()321 Element* Marker::prevSegmentElement()
322 {
323 //it's the same barline
324 return nextSegmentElement();
325 }
326
327 //---------------------------------------------------------
328 // accessibleInfo
329 //---------------------------------------------------------
330
accessibleInfo() const331 QString Marker::accessibleInfo() const
332 {
333 return QString("%1: %2").arg(Element::accessibleInfo(), markerTypeUserName());
334 }
335
336 }
337
338