1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2002-2017 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 #ifndef __ELEMENT_H__
14 #define __ELEMENT_H__
15 
16 #include "elementgroup.h"
17 #include "spatium.h"
18 #include "fraction.h"
19 #include "scoreElement.h"
20 #include "shape.h"
21 #include "sig.h"
22 #include "sym.h"
23 
24 namespace Ms {
25 
26 #ifdef Q_OS_MAC
27 #define CONTROL_MODIFIER Qt::AltModifier
28 #else
29 #define CONTROL_MODIFIER Qt::ControlModifier
30 #endif
31 
32 #ifndef VOICES
33 #define VOICES 4
34 #endif
35 
36 class XmlReader;
37 class XmlWriter;
38 enum class Pid;
39 class StaffType;
40 
41 //---------------------------------------------------------
42 //   Grip
43 //---------------------------------------------------------
44 
45 enum class Grip {
46       NO_GRIP = -1,
47       START = 0, END = 1,                         // arpeggio etc.
48           MIDDLE = 2, APERTURE = 3,               // Line
49       /*START, END , */
50           BEZIER1 = 2, SHOULDER = 3, BEZIER2 = 4, DRAG = 5, // Slur
51       GRIPS = 6                     // number of grips for slur
52       };
53 
54 //---------------------------------------------------------
55 //   OffsetChange
56 //---------------------------------------------------------
57 
58 enum class OffsetChange {
59       RELATIVE_OFFSET   = -1,
60       NONE              =  0,
61       ABSOLUTE_OFFSET   =  1
62       };
63 
64 //---------------------------------------------------------
65 //   ElementFlag
66 //---------------------------------------------------------
67 
68 enum class ElementFlag {
69       NOTHING                = 0x00000000,
70       DROP_TARGET            = 0x00000001,
71       NOT_SELECTABLE         = 0x00000002,
72       MOVABLE                = 0x00000004,
73       COMPOSITION            = 0x00000008,       // true if element is part of another element
74       HAS_TAG                = 0x00000010,       // true if this is a layered element
75       ON_STAFF               = 0x00000020,
76       SELECTED               = 0x00000040,
77       GENERATED              = 0x00000080,
78       INVISIBLE              = 0x00000100,
79       NO_AUTOPLACE           = 0x00000200,
80       SYSTEM                 = 0x00000400,
81       PLACE_ABOVE            = 0x00000800,
82       SIZE_SPATIUM_DEPENDENT = 0x00001000,
83 
84       // measure flags
85       REPEAT_END             = 0x00002000,
86       REPEAT_START           = 0x00004000,
87       REPEAT_JUMP            = 0x00008000,
88       IRREGULAR              = 0x00010000,
89       LINE_BREAK             = 0x00020000,
90       PAGE_BREAK             = 0x00040000,
91       SECTION_BREAK          = 0x00080000,
92       NO_BREAK               = 0x00100000,
93       HEADER                 = 0x00200000,
94       TRAILER                = 0x00400000,    // also used in segment
95       KEYSIG                 = 0x00800000,
96 
97       // segment flags
98       ENABLED                = 0x01000000,    // used for segments
99       EMPTY                  = 0x02000000,
100       WRITTEN                = 0x04000000,
101       };
102 
103 typedef QFlags<ElementFlag> ElementFlags;
104 Q_DECLARE_OPERATORS_FOR_FLAGS(ElementFlags);
105 
106 class ElementEditData;
107 
108 //---------------------------------------------------------
109 //   EditData
110 //    used in editDrag
111 //---------------------------------------------------------
112 
113 class EditData {
114       QList<ElementEditData*> data;
115 
116    public:
117       MuseScoreView* view              { 0       };
118 
119       QVector<QRectF> grip;
120       int grips                        { 0       };         // number of grips
121       Grip curGrip                     { Grip(0) };
122 
123       QPointF pos;
124       QPointF startMove;
125       QPointF normalizedStartMove; ///< Introduced for transition of drag logic. Don't use in new code.
126       QPoint  startMovePixel;
127       QPointF lastPos;
128       QPointF delta; ///< This property is deprecated, use evtDelta or moveDelta instead. In normal drag equals to moveDelta, in edit drag - to evtDelta
129       QPointF evtDelta; ///< Mouse offset for the last mouse move event
130       QPointF moveDelta; ///< Mouse offset from the start of mouse move
131       bool hRaster                     { false };
132       bool vRaster                     { false };
133 
134       int key                          { 0     };
135       Qt::KeyboardModifiers modifiers  { /*0*/ };   // '0' initialized via default constructor, doing it here too results in compiler warning with Qt 5.15
136       QString s;
137 
138       Qt::MouseButtons buttons         { Qt::NoButton };
139 
140       // drop data:
141       QPointF dragOffset;
142       Element* element                 { 0     };
143       Element* dropElement             { 0     };
144 
view(v)145       EditData(MuseScoreView* v = nullptr) : view(v) {}
146       void clearData();
147 
148       ElementEditData* getData(const Element*) const;
149       void addData(ElementEditData*);
150       bool control(bool textEditing = false) const;
shift()151       bool shift() const    { return modifiers & Qt::ShiftModifier; }
isStartEndGrip()152       bool isStartEndGrip() { return curGrip == Grip::START || curGrip == Grip::END; }
153       };
154 
155 //-------------------------------------------------------------------
156 //    @@ Element
157 ///     \brief Base class of score layout elements
158 ///
159 ///     The Element class is the virtual base class of all
160 ///     score layout elements.
161 //-------------------------------------------------------------------
162 
163 class Element : public ScoreElement {
164       Element* _parent { 0 };
165       mutable QRectF _bbox;       ///< Bounding box relative to _pos + _offset
166       qreal _mag;                 ///< standard magnification (derived value)
167       QPointF _pos;               ///< Reference position, relative to _parent, set by autoplace
168       QPointF _offset;            ///< offset from reference position, set by autoplace or user
169       OffsetChange  _offsetChanged; ///< set by user actions that change offset, used by autoplace
170       QPointF _changedPos;        ///< position set when changing offset
171       Spatium _minDistance;       ///< autoplace min distance
172       int _track;                 ///< staffIdx * VOICES + voice
173       mutable ElementFlags _flags;
174                                   ///< valid after call to layout()
175       uint _tag;                  ///< tag bitmask
176 
177    public:
178       enum class EditBehavior {
179             SelectOnly,
180             Edit,
181             };
182 
183   protected:
184       mutable int _z;
185       QColor _color;              ///< element color attribute
186 
187    public:
188       Element(Score* = 0, ElementFlags = ElementFlag::NOTHING);
189       Element(const Element&);
190       virtual ~Element();
191 
192       Element &operator=(const Element&) = delete;
193       //@ create a copy of the element
194       Q_INVOKABLE virtual Ms::Element* clone() const = 0;
195       virtual Element* linkedClone();
196 
197       void deleteLater();
198 
parent()199       Element* parent() const                 { return _parent;     }
setParent(Element * e)200       void setParent(Element* e)              { _parent = e;        }
201 
202       Element* findAncestor(ElementType t);
203       const Element* findAncestor(ElementType t) const;
204 
205       Measure* findMeasure();
206       const Measure* findMeasure() const;
207       MeasureBase* findMeasureBase();
208       const MeasureBase* findMeasureBase() const;
209 
isElement()210       virtual bool isElement() const override { return true;        }
211 
212       qreal spatium() const;
213 
setFlag(ElementFlag f,bool v)214       inline void setFlag(ElementFlag f, bool v)       { if (v) _flags |= f; else _flags &= ~ElementFlags(f); }
setFlag(ElementFlag f,bool v)215       inline void setFlag(ElementFlag f, bool v) const { if (v) _flags |= f; else _flags &= ~ElementFlags(f); }
flag(ElementFlag f)216       inline bool flag(ElementFlag f) const            { return _flags & f; }
217 
selected()218       bool selected() const                   { return flag(ElementFlag::SELECTED); }
setSelected(bool f)219       virtual void setSelected(bool f)        { setFlag(ElementFlag::SELECTED, f);  }
220 
visible()221       bool visible() const                    { return !flag(ElementFlag::INVISIBLE);  }
setVisible(bool f)222       virtual void setVisible(bool f)         { setFlag(ElementFlag::INVISIBLE, !f);   }
223 
sizeIsSpatiumDependent()224       virtual bool sizeIsSpatiumDependent() const override { return !flag(ElementFlag::SIZE_SPATIUM_DEPENDENT); }
setSizeIsSpatiumDependent(bool v)225       void setSizeIsSpatiumDependent(bool v)  { setFlag(ElementFlag::SIZE_SPATIUM_DEPENDENT, !v); }
226       virtual bool offsetIsSpatiumDependent() const override;
227 
placement()228       Placement placement() const             { return Placement(!flag(ElementFlag::PLACE_ABOVE));  }
setPlacement(Placement val)229       void setPlacement(Placement val)        { setFlag(ElementFlag::PLACE_ABOVE, !bool(val)); }
placeAbove()230       bool placeAbove() const                 { return placement() == Placement::ABOVE; }
placeBelow()231       bool placeBelow() const                 { return placement() == Placement::BELOW; }
placeMultiple()232       virtual bool placeMultiple() const      { return true; }
233 
generated()234       bool generated() const                  { return flag(ElementFlag::GENERATED);  }
setGenerated(bool val)235       void setGenerated(bool val)             { setFlag(ElementFlag::GENERATED, val);   }
236 
minDistance()237       Spatium minDistance() const             { return _minDistance;    }
setMinDistance(Spatium v)238       void setMinDistance(Spatium v)          { _minDistance = v;       }
offsetChanged()239       OffsetChange offsetChanged() const      { return _offsetChanged;  }
240       void setOffsetChanged(bool v, bool absolute = true, const QPointF& diff = QPointF());
241 
ipos()242       const QPointF& ipos() const             { return _pos;                    }
pos()243       virtual const QPointF pos() const       { return _pos + _offset;          }
x()244       virtual qreal x() const                 { return _pos.x() + _offset.x(); }
y()245       virtual qreal y() const                 { return _pos.y() + _offset.y(); }
setPos(qreal x,qreal y)246       void setPos(qreal x, qreal y)           { _pos.rx() = x, _pos.ry() = y;   }
setPos(const QPointF & p)247       void setPos(const QPointF& p)           { _pos = p;                }
rpos()248       QPointF& rpos()                         { return _pos;                    }
rxpos()249       qreal& rxpos()                          { return _pos.rx();        }
rypos()250       qreal& rypos()                          { return _pos.ry();        }
move(const QPointF & s)251       virtual void move(const QPointF& s)     { _pos += s;               }
252 
253       virtual QPointF pagePos() const;          ///< position in page coordinates
254       virtual QPointF canvasPos() const;        ///< position in canvas coordinates
255       qreal pageX() const;
256       qreal canvasX() const;
257 
mapFromCanvas(const QPointF & p)258       QPointF mapFromCanvas(const QPointF& p) const { return p - canvasPos(); }
mapToCanvas(const QPointF & p)259       QPointF mapToCanvas(const QPointF& p) const { return p + canvasPos(); }
260 
offset()261       const QPointF& offset() const               { return _offset;  }
setOffset(const QPointF & o)262       virtual void setOffset(const QPointF& o)    { _offset = o;     }
setOffset(qreal x,qreal y)263       void setOffset(qreal x, qreal y)            { _offset.rx() = x, _offset.ry() = y; }
roffset()264       QPointF& roffset()                          { return _offset; }
rxoffset()265       qreal& rxoffset()                           { return _offset.rx(); }
ryoffset()266       qreal& ryoffset()                           { return _offset.ry(); }
267 
268       virtual Fraction tick() const;
269       virtual Fraction rtick() const;
270       virtual Fraction playTick() const; ///< Returns the tick at which playback should begin when this element is selected. Defaults to the element's own tick position.
271 
272       Fraction beat() const;
273 
isNudged()274       bool isNudged() const                       { return !_offset.isNull(); }
275 
bbox()276       virtual const QRectF& bbox() const          { return _bbox;              }
bbox()277       virtual QRectF& bbox()                      { return _bbox;              }
height()278       virtual qreal height() const                { return bbox().height();    }
setHeight(qreal v)279       virtual void setHeight(qreal v)             { _bbox.setHeight(v);        }
width()280       virtual qreal width() const                 { return bbox().width();     }
setWidth(qreal v)281       virtual void setWidth(qreal v)              { _bbox.setWidth(v);         }
abbox()282       QRectF abbox() const                        { return bbox().translated(pagePos());   }
pageBoundingRect()283       QRectF pageBoundingRect() const             { return bbox().translated(pagePos());   }
canvasBoundingRect()284       QRectF canvasBoundingRect() const           { return bbox().translated(canvasPos()); }
setbbox(const QRectF & r)285       virtual void setbbox(const QRectF& r) const { _bbox = r;           }
addbbox(const QRectF & r)286       virtual void addbbox(const QRectF& r) const { _bbox |= r;          }
287       bool contains(const QPointF& p) const;
288       bool intersects(const QRectF& r) const;
289 #ifndef NDEBUG
shape()290       virtual Shape shape() const                 { return Shape(bbox(), name());   }
291 #else
shape()292       virtual Shape shape() const                 { return Shape(bbox());   }
293 #endif
baseLine()294       virtual qreal baseLine() const              { return -height();       }
295 
subtype()296       virtual int subtype() const                 { return -1; }  // for select gui
297 
draw(QPainter *)298       virtual void draw(QPainter*) const {}
drawAt(QPainter * p,const QPointF & pt)299       void drawAt(QPainter*p, const QPointF& pt) const { p->translate(pt); draw(p); p->translate(-pt);}
300 
301       virtual void writeProperties(XmlWriter& xml) const;
302       virtual bool readProperties(XmlReader&);
303 
304       virtual void write(XmlWriter&) const;
305       virtual void read(XmlReader&);
306 
307 //       virtual ElementGroup getElementGroup() { return SingleElementGroup(this); }
getDragGroup(std::function<bool (const Element *)> isDragged)308       virtual std::unique_ptr<ElementGroup> getDragGroup(std::function<bool(const Element*)> isDragged) { Q_UNUSED(isDragged); return std::unique_ptr<ElementGroup>(new SingleElementGroup(this)); }
309 
310       virtual void startDrag(EditData&);
311       virtual QRectF drag(EditData&);
312       virtual void endDrag(EditData&);
313       /** Returns anchor lines displayed while dragging element in canvas coordinates. */
dragAnchorLines()314       virtual QVector<QLineF> dragAnchorLines() const       { return QVector<QLineF>(); }
315       /**
316        * A generic \ref dragAnchorLines() implementation which can be used in
317        * dragAnchorLines() overrides in descendants. It is not made its default
318        * implementation in Element class since showing anchor lines is not
319        * desirable for most element types.
320        * TODO: maybe Annotation class could be extracted which would be a base
321        * class of various annotation types and which would have this
322        * dragAnchorLines() implementation by default.
323        */
324       QVector<QLineF> genericDragAnchorLines() const;
325 
isEditable()326       virtual bool isEditable() const         { return !flag(ElementFlag::GENERATED); }
327 
328       virtual void startEdit(EditData&);
329       virtual bool edit(EditData&);
330       virtual void startEditDrag(EditData&);
331       virtual void editDrag(EditData&);
332       virtual void endEditDrag(EditData&);
333       virtual void endEdit(EditData&);
334 
editCut(EditData &)335       virtual void editCut(EditData&)            {}
editCopy(EditData &)336       virtual void editCopy(EditData&)           {}
337 
338       void updateGrips(EditData&) const;
339       virtual bool nextGrip(EditData&) const;
340       virtual bool prevGrip(EditData&) const;
341       /** Returns anchor lines displayed while dragging element's grip in canvas coordinates. */
gripAnchorLines(Grip)342       virtual QVector<QLineF> gripAnchorLines(Grip) const     { return QVector<QLineF>(); }
343 
normalModeEditBehavior()344       virtual EditBehavior normalModeEditBehavior() const { return EditBehavior::SelectOnly; }
gripsCount()345       virtual int gripsCount() const { return 0; }
initialEditModeGrip()346       virtual Grip initialEditModeGrip() const { return Grip::NO_GRIP; }
defaultGrip()347       virtual Grip defaultGrip() const { return Grip::NO_GRIP; }
348       /** Returns grips positions in page coordinates. */
349       virtual std::vector<QPointF> gripsPositions(const EditData& = EditData()) const { return std::vector<QPointF>(); }
350 
track()351       int track() const                       { return _track; }
setTrack(int val)352       virtual void setTrack(int val)          { _track = val;  }
353 
354       int z() const;
setZ(int val)355       void setZ(int val)                      { _z = val;  }
356 
staffIdx()357       int staffIdx() const                    { return _track >> 2;        }
vStaffIdx()358       virtual int vStaffIdx() const           { return staffIdx();         }
voice()359       int voice() const                       { return _track & 3;         }
setVoice(int v)360       void setVoice(int v)                    { _track = (_track / VOICES) * VOICES + v; }
361       Staff* staff() const;
362       const StaffType* staffType() const;
363       bool onTabStaff() const;
364       Part* part() const;
365 
366       virtual void add(Element*);
367       virtual void remove(Element*);
368       virtual void change(Element* o, Element* n);
369 
layout()370       virtual void layout() {}
371       virtual void spatiumChanged(qreal /*oldValue*/, qreal /*newValue*/);
372       virtual void localSpatiumChanged(qreal /*oldValue*/, qreal /*newValue*/);
373 
374       // debug functions
375       virtual void dump() const;
376       virtual Q_INVOKABLE QString subtypeName() const;
377       //@ Returns the human-readable name of the element type
378       //@ Returns the name of the element type
_name()379       virtual Q_INVOKABLE QString _name() const { return QString(name()); }
380 
color()381       virtual QColor color() const             { return _color; }
382       QColor curColor() const;
383       QColor curColor(bool isVisible) const;
384       QColor curColor(bool isVisible, QColor normalColor) const;
setColor(const QColor & c)385       virtual void setColor(const QColor& c)     { _color = c;    }
386       void undoSetColor(const QColor& c);
387       void undoSetVisible(bool v);
388 
389       static ElementType readType(XmlReader& node, QPointF*, Fraction*);
390       static Element* readMimeData(Score* score, const QByteArray& data, QPointF*, Fraction*);
391 
392       virtual QByteArray mimeData(const QPointF&) const;
393 /**
394  Return true if this element accepts a drop at canvas relative \a pos
395  of given element \a type and \a subtype.
396 
397  Reimplemented by elements that accept drops. Used to change cursor shape while
398  dragging to indicate drop targets.
399 */
acceptDrop(EditData &)400       virtual bool acceptDrop(EditData&) const { return false; }
401 
402 /**
403  Handle a dropped element at canvas relative \a pos of given element
404  \a type and \a subtype. Returns dropped element if any.
405  The ownership of element in DropData is transferred to the called
406  element (if not used, element has to be deleted).
407  The returned element will be selected if not in note edit mode.
408 
409  Reimplemented by elements that accept drops.
410 */
drop(EditData &)411       virtual Element* drop(EditData&) { return 0;}
412 
413 /**
414  delivers mouseEvent to element in edit mode
415  returns true if mouse event is accepted by element
416  */
mousePress(EditData &)417       virtual bool mousePress(EditData&) { return false; }
418 
419       mutable bool itemDiscovered      { false };     ///< helper flag for bsp
420 
421       virtual void scanElements(void* data, void (*func)(void*, Element*), bool all=true);
422 
423       virtual void reset() override;         // reset all properties & position to default
424 
mag()425       virtual qreal mag() const        { return _mag;   }
setMag(qreal val)426       void setMag(qreal val)           { _mag = val;    }
427       qreal magS() const;
428 
429       bool isPrintable() const;
point(const Spatium sp)430       qreal point(const Spatium sp) const { return sp.val() * spatium(); }
431 
432       static Ms::Element* create(Ms::ElementType type, Score*);
433       static Element* name2Element(const QStringRef&, Score*);
434 
systemFlag()435       bool systemFlag() const          { return flag(ElementFlag::SYSTEM);  }
setSystemFlag(bool v)436       void setSystemFlag(bool v) const { setFlag(ElementFlag::SYSTEM, v);  }
437 
header()438       bool header() const              { return flag(ElementFlag::HEADER);        }
setHeader(bool v)439       void setHeader(bool v)           { setFlag(ElementFlag::HEADER, v);         }
440 
trailer()441       bool trailer() const             { return flag(ElementFlag::TRAILER); }
setTrailer(bool val)442       void setTrailer(bool val)        { setFlag(ElementFlag::TRAILER, val); }
443 
selectable()444       bool selectable() const          { return !flag(ElementFlag::NOT_SELECTABLE);  }
setSelectable(bool val)445       void setSelectable(bool val)     { setFlag(ElementFlag::NOT_SELECTABLE, !val); }
446 
dropTarget()447       bool dropTarget() const          { return flag(ElementFlag::DROP_TARGET); }
setDropTarget(bool v)448       void setDropTarget(bool v) const { setFlag(ElementFlag::DROP_TARGET, v);  }
449 
composition()450       bool composition() const          { return flag(ElementFlag::COMPOSITION); }
setComposition(bool v)451       void setComposition(bool v) const { setFlag(ElementFlag::COMPOSITION, v);  }
452 
isMovable()453       virtual bool isMovable() const   { return flag(ElementFlag::MOVABLE);     }
454 
enabled()455       bool enabled() const             { return flag(ElementFlag::ENABLED); }
setEnabled(bool val)456       void setEnabled(bool val)        { setFlag(ElementFlag::ENABLED, val); }
457 
tag()458       uint tag() const                 { return _tag;                      }
setTag(uint val)459       void setTag(uint val)            { _tag = val;                       }
460 
461       bool autoplace() const;
setAutoplace(bool v)462       virtual void setAutoplace(bool v)   { setFlag(ElementFlag::NO_AUTOPLACE, !v); }
addToSkyline()463       bool addToSkyline() const           { return !(_flags & (ElementFlag::INVISIBLE|ElementFlag::NO_AUTOPLACE)); }
464 
465       virtual QVariant getProperty(Pid) const override;
466       virtual bool setProperty(Pid, const QVariant&) override;
467       virtual void undoChangeProperty(Pid id, const QVariant&, PropertyFlags ps) override;
468       using ScoreElement::undoChangeProperty;
469       virtual QVariant propertyDefault(Pid) const override;
470       virtual Pid propertyId(const QStringRef& xmlName) const override;
propertyUserValue(Pid)471       virtual QString propertyUserValue(Pid) const override;
472       virtual Element* propertyDelegate(Pid) { return 0; }  // return Spanner for SpannerSegment for some properties
473 
474       bool custom(Pid) const;
475       virtual bool isUserModified() const;
476 
477       void drawSymbol(SymId id, QPainter* p, const QPointF& o = QPointF(), qreal scale = 1.0) const;
478       void drawSymbol(SymId id, QPainter* p, const QPointF& o, int n) const;
479       void drawSymbols(const std::vector<SymId>&, QPainter* p, const QPointF& o = QPointF(), qreal scale = 1.0) const;
480       void drawSymbols(const std::vector<SymId>&, QPainter* p, const QPointF& o, const QSizeF& scale) const;
481       qreal symHeight(SymId id) const;
482       qreal symWidth(SymId id) const;
483       qreal symWidth(const std::vector<SymId>&) const;
484       QRectF symBbox(SymId id) const;
485       QRectF symBbox(const std::vector<SymId>&) const;
486       QPointF symStemDownNW(SymId id) const;
487       QPointF symStemUpSE(SymId id) const;
488       QPointF symStemDownSW(SymId id) const;
489       QPointF symStemUpNW(SymId id) const;
490       QPointF symCutOutNE(SymId id) const;
491       QPointF symCutOutNW(SymId id) const;
492       QPointF symCutOutSE(SymId id) const;
493       QPointF symCutOutSW(SymId id) const;
494       qreal symAdvance(SymId id) const;
495       bool symIsValid(SymId id) const;
496 
497       bool concertPitch() const;
498       virtual Element* nextElement(); // selects the next score element, (notes, rests etc. as well as articulation etc.)
499       virtual Element* prevElement(); // selects the next score element, (notes, rests etc. as well as articulation etc.)
500       virtual Element* nextSegmentElement();  //< Used for navigation
501       virtual Element* prevSegmentElement();  //< next-element and prev-element command
502 
503       virtual QString accessibleInfo() const;         //< used to populate the status bar
screenReaderInfo()504       virtual QString screenReaderInfo() const  {     //< by default returns accessibleInfo, but can be overridden
505             return accessibleInfo();
506             }
507                                                        //  if the screen-reader needs a special string (see note for example)
accessibleExtraInfo()508       virtual QString accessibleExtraInfo() const {    // used to return info that will be appended to accessibleInfo
509             return QString();                          // and passed only to the screen-reader
510             }
511 
512       virtual void triggerLayout() const;
513       virtual void triggerLayoutAll() const;
514       virtual void drawEditMode(QPainter*, EditData&);
515 
516       void autoplaceSegmentElement(bool above, bool add);        // helper functions
517       void autoplaceMeasureElement(bool above, bool add);
518       void autoplaceSegmentElement(bool add = true) { autoplaceSegmentElement(placeAbove(), add); }
519       void autoplaceMeasureElement(bool add = true) { autoplaceMeasureElement(placeAbove(), add); }
520       void autoplaceCalculateOffset(QRectF& r, qreal minDistance);
521       qreal rebaseOffset(bool nox = true);
522       bool rebaseMinDistance(qreal& md, qreal& yd, qreal sp, qreal rebase, bool above, bool fix);
523 
524       qreal styleP(Sid idx) const;
525       };
526 
527 //-----------------------------------------------------------------------------
528 //   ElementEditData
529 //    holds element specific data during element editing:
530 //
531 //    startEditDrag(EditData&)    creates data and attaches it to EditData
532 //       editDrag(EditData&)
533 //    endEditDrag(EditData&)      use data to create undo records
534 //-----------------------------------------------------------------------------
535 
536 enum class EditDataType : signed char {
537       ElementEditData,
538       TextEditData,
539       BarLineEditData,
540       BeamEditData,
541       NoteEditData,
542       };
543 
544 struct PropertyData {
545       Pid id;
546       QVariant data;
547       PropertyFlags f;
548       };
549 
550 class ElementEditData {
551    public:
552       Element* e;
553       QList<PropertyData> propertyData;
554       QPointF initOffset; ///< for dragging: difference between actual offset and editData.moveDelta
555 
556       virtual ~ElementEditData() = default;
pushProperty(Pid pid)557       void pushProperty(Pid pid) { propertyData.push_back(PropertyData({ pid, e->getProperty(pid), e->propertyFlags(pid) })); }
type()558       virtual EditDataType type()   { return EditDataType::ElementEditData; }
559       };
560 
561 //---------------------------------------------------------
562 //   ElementList
563 //---------------------------------------------------------
564 
565 class ElementList : public std::vector<Element*> {
566    public:
ElementList()567       ElementList() {}
568       bool remove(Element*);
569       void replace(Element* old, Element* n);
570       void write(XmlWriter&) const;
571       void write(XmlWriter&, const char* name) const;
572       };
573 
574 //---------------------------------------------------------
575 //   @@ Compound
576 //---------------------------------------------------------
577 
578 class Compound : public Element {
579       QList<Element*> elements;
580 
581    protected:
getElements()582       const QList<Element*>& getElements() const { return elements; }
583 
584    public:
585       Compound(Score*);
586       Compound(const Compound&);
587       virtual ElementType type() const = 0;
588 
589       virtual void draw(QPainter*) const;
590       virtual void addElement(Element*, qreal x, qreal y);
591       void clear();
592       virtual void setSelected(bool f);
593       virtual void setVisible(bool);
594       virtual void layout();
595       };
596 
597 extern bool elementLessThan(const Element* const, const Element* const);
598 extern void collectElements(void* data, Element* e);
599 
600 
601 }     // namespace Ms
602 
603 Q_DECLARE_METATYPE(Ms::ElementType);
604 
605 #endif
606 
607