File: element.h

package info (click to toggle)
musescore 2.0.3%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 202,532 kB
  • ctags: 58,769
  • sloc: cpp: 257,595; xml: 172,226; ansic: 139,931; python: 6,565; sh: 6,383; perl: 423; makefile: 290; awk: 142; pascal: 67; sed: 3
file content (711 lines) | stat: -rw-r--r-- 27,469 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
//=============================================================================
//  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
//=============================================================================

#ifndef __ELEMENT_H__
#define __ELEMENT_H__

#include "mscore.h"
#include "spatium.h"
#include "fraction.h"
#include "scoreElement.h"

class QPainter;

namespace Ms {

/**
 \file
 Definition of classes Element, ElementList, StaffLines.
*/


class Xml;
class Measure;
class Staff;
class Part;
class Score;
class Sym;
class MuseScoreView;
class Segment;
class TextStyle;
class Element;
enum class SymId;

//---------------------------------------------------------
//   Grip
//---------------------------------------------------------

enum class Grip : signed char {
      NO_GRIP = -1,
      START = 0, END = 1,                         // arpeggio etc.
          MIDDLE = 2, APERTURE = 3,               // Line
      /*START, END , */
          BEZIER1 = 2, SHOULDER = 3, BEZIER2 = 4, DRAG = 5, // Slur
      GRIPS = 6                     // number of grips for slur
      };

//---------------------------------------------------------
//   ElementFlag
//---------------------------------------------------------

enum class ElementFlag : char {
      DROP_TARGET  = 0x2,
      SELECTABLE   = 0x4,
      MOVABLE      = 0x8,
      SEGMENT      = 0x10,
      HAS_TAG      = 0x20,
      ON_STAFF     = 0x40   // parent is Segment() type
      };

typedef QFlags<ElementFlag> ElementFlags;
Q_DECLARE_OPERATORS_FOR_FLAGS(ElementFlags);

//---------------------------------------------------------
///   \brief Unit of horizontal measure
//    represent the space used by a Segment
//---------------------------------------------------------

class Space {
      qreal _lw { 0.0 };       // space needed to the left
      qreal _rw { 0.0 };       // space needed to the right

   public:
      Space() {}
      Space(qreal a, qreal b) : _lw(a), _rw(b) {}
      qreal lw() const             { return _lw; }
      qreal rw() const             { return _rw; }
      qreal width() const          { return _lw + _rw; }
      void setLw(qreal e)          { _lw = e; }
      void setRw(qreal m)          { _rw = m; }
      void addL(qreal v)           { _lw += v; }
      void addR(qreal v)           { _rw += v; }
      void max(const Space& s);
      Space& operator+=(const Space& s) {
            _lw += s._lw;
            _rw += s._rw;
            return *this;
            }
      };

//---------------------------------------------------------
//   DropData
//---------------------------------------------------------

struct DropData {
      MuseScoreView* view;
      QPointF pos;
      QPointF dragOffset;
      Element* element;
      Qt::KeyboardModifiers modifiers;
      Fraction duration;

      DropData();
      };

//---------------------------------------------------------
//   EditData
//    used in editDrag
//---------------------------------------------------------

struct EditData {
      MuseScoreView* view;
      Grip curGrip;
      QPointF startMove;
      QPointF pos;
      QPointF lastPos;
      QPointF delta;
      bool hRaster;
      bool vRaster;
      };

//---------------------------------------------------------
//   ElementName
//---------------------------------------------------------

struct ElementName {
      const char* name;
      const char* userName;
      ElementName(const char* _name, const char* _userName) : name(_name), userName(_userName) {}
      };

//-------------------------------------------------------------------
//    @@ Element
///     \brief Base class of score layout elements
///
///     The Element class is the virtual base class of all
///     score layout elements.
//
//    @P bbox       rect                  bounding box relative to pos and userOff (read only)
//    @P color      color                 element drawing color
//    @P generated  bool                  true if the element has been generated by layout
//    @P pagePos    point                 position in page coordinated (read only)
//    @P parent     Element               the parent element in drawing hierarchy
//    @P placement  enum (Element.ABOVE, Element.BELOW)
//    @P pos        point                 position relative to parent
//    @P selected   bool                  true if the element is currently selected
//    @P track      int                   the track the elment belongs to
//    @P type       enum (Element.ACCIDENTAL, .ACCIDENTAL, .AMBITUS, .ARPEGGIO, .BAGPIPE_EMBELLISHMENT, .BAR_LINE, .BEAM, .BEND, .BRACKET, .BREATH, .CHORD, .CHORDLINE, .CLEF, .COMPOUND, .DYNAMIC, .ELEMENT, .ELEMENT_LIST, .FBOX, .FIGURED_BASS, .FINGERING, .FRET_DIAGRAM, .FSYMBOL, .GLISSANDO, .GLISSANDO_SEGMENT, .HAIRPIN, .HAIRPIN_SEGMENT, .HARMONY, .HBOX, .HOOK, .ICON, .IMAGE, .INSTRUMENT_CHANGE, .INSTRUMENT_NAME, .JUMP, .KEYSIG, .LASSO, .LAYOUT_BREAK, .LEDGER_LINE, .LINE, .LYRICS, .LYRICSLINE, .LYRICSLINE_SEGMENT, .MARKER, .MEASURE, .MEASURE_LIST, .NOTE, .NOTEDOT, .NOTEHEAD, .NOTELINE, .OSSIA, .OTTAVA, .OTTAVA_SEGMENT, .PAGE, .PEDAL, .PEDAL_SEGMENT, .REHEARSAL_MARK, .REPEAT_MEASURE, .REST, .SEGMENT, .SELECTION, .SHADOW_NOTE, .SLUR, .SLUR_SEGMENT, .SPACER, .STAFF_LINES, .STAFF_LIST, .STAFF_STATE, .STAFF_TEXT, .STEM, .STEM_SLASH, .SYMBOL, .SYSTEM, .TAB_DURATION_SYMBOL, .TBOX, .TEMPO_TEXT, .TEXT, .TEXTLINE, .TEXTLINE_SEGMENT, .TIE, .TIMESIG, .TREMOLO, .TREMOLOBAR, .TRILL, .TRILL_SEGMENT, .TUPLET, .VBOX, .VOLTA, .VOLTA_SEGMENT) (read only)
//    @P userOff    point                 manual offset to position determined by layout
//    @P visible    bool
//-------------------------------------------------------------------

class Element : public QObject, public ScoreElement {
      Q_OBJECT
      Q_ENUMS(Type)
      Q_ENUMS(Placement)

      Q_PROPERTY(QRectF                   bbox        READ scriptBbox )
      Q_PROPERTY(QColor                   color       READ color        WRITE undoSetColor)
      Q_PROPERTY(bool                     generated   READ generated    WRITE setGenerated)
      Q_PROPERTY(QPointF                  pagePos     READ scriptPagePos)
      Q_PROPERTY(Ms::Element*             parent      READ parent       WRITE setParent)
      Q_PROPERTY(Ms::Element::Placement   placement   READ placement    WRITE undoSetPlacement)
      Q_PROPERTY(QPointF                  pos         READ scriptPos    WRITE scriptSetPos)
      Q_PROPERTY(bool                     selected    READ selected     WRITE setSelected)
      Q_PROPERTY(qreal                    spatium     READ spatium)
      Q_PROPERTY(int                      track       READ track        WRITE setTrack)
      Q_PROPERTY(Ms::Element::Type        type        READ type)
      Q_PROPERTY(QPointF                  userOff     READ scriptUserOff WRITE scriptSetUserOff)
      Q_PROPERTY(bool                     visible     READ visible      WRITE undoSetVisible)

      Element* _parent { 0 };

      bool _generated;            ///< automatically generated Element

  protected:
      bool _selected;             ///< set if element is selected
      bool _visible;              ///< visibility attribute
      QColor _color;              ///< element color attribute

  public:
      //-------------------------------------------------------------------
      //    The value of this enum determines the "stacking order"
      //    of elements on the canvas.
      //   Note: keep in sync with array elementNames[] in element.cpp
      //-------------------------------------------------------------------
      enum class Type : char {
            INVALID = 0,
            SYMBOL,
            TEXT,
            INSTRUMENT_NAME,
            SLUR_SEGMENT,
            STAFF_LINES,
            BAR_LINE,
            STEM_SLASH,
            LINE,

            ARPEGGIO,
            ACCIDENTAL,
            STEM,             // list STEM before NOTE: notes in TAB might 'break' stems
            NOTE,             // and this requires stems to be drawn before notes
            CLEF,             // elements from CLEF to TIMESIG need to be in the order
            KEYSIG,           // in which they appear in a measure
            AMBITUS,
            TIMESIG,
            REST,
            BREATH,

            REPEAT_MEASURE,
            IMAGE,
            TIE,
            ARTICULATION,
            CHORDLINE,
            DYNAMIC,
            BEAM,
            HOOK,
            LYRICS,
            FIGURED_BASS,

            MARKER,
            JUMP,
            FINGERING,
            TUPLET,
            TEMPO_TEXT,
            STAFF_TEXT,
            REHEARSAL_MARK,
            INSTRUMENT_CHANGE,
            HARMONY,
            FRET_DIAGRAM,
            BEND,
            TREMOLOBAR,
            VOLTA,
            HAIRPIN_SEGMENT,
            OTTAVA_SEGMENT,
            TRILL_SEGMENT,
            TEXTLINE_SEGMENT,
            VOLTA_SEGMENT,
            PEDAL_SEGMENT,
            LYRICSLINE_SEGMENT,
            GLISSANDO_SEGMENT,
            LAYOUT_BREAK,
            SPACER,
            STAFF_STATE,
            LEDGER_LINE,
            NOTEHEAD,
            NOTEDOT,
            TREMOLO,
            MEASURE,
            SELECTION,
            LASSO,
            SHADOW_NOTE,
            TAB_DURATION_SYMBOL,
            FSYMBOL,
            PAGE,
            HAIRPIN,
            OTTAVA,
            PEDAL,
            TRILL,
            TEXTLINE,
            NOTELINE,
            LYRICSLINE,
            GLISSANDO,
            BRACKET,

            SEGMENT,
            SYSTEM,
            COMPOUND,
            CHORD,
            SLUR,
            ELEMENT,
            ELEMENT_LIST,
            STAFF_LIST,
            MEASURE_LIST,
            HBOX,
            VBOX,
            TBOX,
            FBOX,
            ICON,
            OSSIA,
            BAGPIPE_EMBELLISHMENT,

            MAXTYPE
            };

      enum class Placement : char {
            ABOVE, BELOW
            };

  private:
      Placement _placement;

      mutable ElementFlags _flags;

      int _track;                 ///< staffIdx * VOICES + voice
      qreal _mag;                 ///< standard magnification (derived value)

      QPointF _pos;               ///< Reference position, relative to _parent.
      QPointF _userOff;           ///< offset from normal layout position:
                                  ///< user dragged object this amount.
      QPointF _readPos;

      mutable QRectF _bbox;       ///< Bounding box relative to _pos + _userOff
                                  ///< valid after call to layout()
      uint _tag;                  ///< tag bitmask
   protected:
      QPointF _startDragPosition;   ///< used during drag

   public:
      Element(Score* s = 0);
      Element(const Element&);
      virtual ~Element();
      Element &operator=(const Element&) = delete;
      //@ create a copy of the element
      Q_INVOKABLE virtual Ms::Element* clone() const = 0;
      virtual Element* linkedClone();

      Element* parent() const                 { return _parent;     }
      void setParent(Element* e)              { _parent = e;        }
      Element* findMeasure();

      qreal spatium() const;

      bool selected() const                   { return _selected;   }
      virtual void setSelected(bool f)        { _selected = f;      }

      bool visible() const                    { return _visible;    }
      virtual void setVisible(bool f)         { _visible = f;       }

      Placement placement() const             { return _placement;  }
      void setPlacement(Placement val)        { _placement = val;   }
      void undoSetPlacement(Placement val);

      bool generated() const                  { return _generated;  }
      void setGenerated(bool val)             { _generated = val;   }

      const QPointF& ipos() const             { return _pos;                    }
      virtual const QPointF pos() const       { return _pos + _userOff;         }
      virtual qreal x() const                 { return _pos.x() + _userOff.x(); }
      virtual qreal y() const                 { return _pos.y() + _userOff.y(); }
      void setPos(qreal x, qreal y)           { _pos.rx() = x, _pos.ry() = y;   }
      void setPos(const QPointF& p)           { _pos = p;                }
      qreal& rxpos()                          { return _pos.rx();        }
      qreal& rypos()                          { return _pos.ry();        }
      virtual void move(const QPointF& s)     { _pos += s;               }

      virtual QPointF pagePos() const;          ///< position in page coordinates
      virtual QPointF canvasPos() const;        ///< position in canvas coordinates
      qreal pageX() const;
      qreal canvasX() const;

      const QPointF& userOff() const          { return _userOff;  }
      virtual void setUserOff(const QPointF& o)       { _userOff = o;     }
      void setUserXoffset(qreal v)            { _userOff.setX(v); }
      void setUserYoffset(qreal v)            { _userOff.setY(v); }

      qreal& rUserXoffset()                   { return _userOff.rx(); }
      qreal& rUserYoffset()                   { return _userOff.ry(); }

      // function versions for scripts: use coords in spatium units rather than raster
      // and route pos changes to userOff
      QRectF scriptBbox() const;
      virtual QPointF scriptPagePos() const;
      virtual QPointF scriptPos() const;
      void scriptSetPos(const QPointF& p);
      QPointF scriptUserOff() const;
      void scriptSetUserOff(const QPointF& o);

      bool isNudged() const                   { return !(_readPos.isNull() && _userOff.isNull()); }

      const QPointF& readPos() const          { return _readPos;   }
      void setReadPos(const QPointF& p)       { _readPos = p;      }
      virtual void adjustReadPos();

      virtual const QRectF& bbox() const      { return _bbox;              }
      virtual QRectF& bbox()                  { return _bbox;              }
      virtual qreal height() const            { return bbox().height();    }
      virtual void setHeight(qreal v)         { _bbox.setHeight(v);        }
      virtual qreal width() const             { return bbox().width();     }
      virtual void setWidth(qreal v)          { _bbox.setWidth(v);         }
      QRectF abbox() const                        { return bbox().translated(pagePos());   }
      QRectF pageBoundingRect() const             { return bbox().translated(pagePos());   }
      QRectF canvasBoundingRect() const           { return bbox().translated(canvasPos()); }
      virtual void setbbox(const QRectF& r) const { _bbox = r;           }
      virtual void addbbox(const QRectF& r) const { _bbox |= r;          }
      virtual bool contains(const QPointF& p) const;
      bool intersects(const QRectF& r) const;
      virtual QPainterPath shape() const;
      virtual qreal baseLine() const          { return -height();       }

      virtual Element::Type type() const = 0;
      virtual int subtype() const   { return -1; }  // for select gui

      bool isRest() const      { return type() == Element::Type::REST; }
      bool isChord() const     { return type() == Element::Type::CHORD; }
      bool isMeasure() const   { return type() == Element::Type::MEASURE; }
      bool isChordRest() const { return type() == Element::Type::REST || type() == Element::Type::CHORD || type() == Element::Type::REPEAT_MEASURE; }

      bool isDurationElement() const { return isChordRest() || (type() == Element::Type::TUPLET); }
      bool isSLine() const;
      bool isSLineSegment() const;

      virtual void draw(QPainter*) const {}

      virtual void writeProperties(Xml& xml) const;
      virtual bool readProperties(XmlReader&);

      virtual void write(Xml&) const;
      virtual void read(XmlReader&);

      virtual QRectF drag(EditData*);
      virtual void endDrag()                  {}
      virtual QLineF dragAnchor() const       { return QLineF(); }

      virtual bool isEditable() const         { return !_generated; }
      virtual void startEdit(MuseScoreView*, const QPointF&);
      virtual bool edit(MuseScoreView*, Grip, int key, Qt::KeyboardModifiers, const QString& s);
      virtual void editDrag(const EditData&);
      virtual void endEditDrag()                               {}
      virtual void endEdit()                                   {}
      virtual void updateGrips(Grip*, QVector<QRectF>&) const      { }
      virtual bool nextGrip(Grip*) const;
      virtual int grips() const                { return 0; }
      virtual bool prevGrip(Grip*) const;
      virtual QPointF gripAnchor(Grip) const   { return QPointF(); }
      virtual void setGrip(Grip, const QPointF&);
      virtual QPointF getGrip(Grip) const;

      int track() const                       { return _track; }
      virtual void setTrack(int val)          { _track = val;  }

      virtual int z() const                   { return int(type()) * 100; }  // stacking order

      int staffIdx() const                    { return _track >> 2;        }
      int voice() const                       { return _track & 3;         }
      void setVoice(int v)                    { _track = (_track / VOICES) * VOICES + v; }
      Staff* staff() const;
      Part* part() const;

      virtual void add(Element*);
      virtual void remove(Element*);
      virtual void change(Element* o, Element* n);

      virtual void layout() {}
      virtual void spatiumChanged(qreal /*oldValue*/, qreal /*newValue*/);
      virtual void localSpatiumChanged(qreal /*oldValue*/, qreal /*newValue*/);

      // debug functions
      virtual void dump() const;
      const char* name() const;
      virtual Q_INVOKABLE QString subtypeName() const;
      //@ Returns the human-readable name of the element type
      virtual Q_INVOKABLE QString userName() const;
      //@ Returns the name of the element type
      virtual Q_INVOKABLE QString _name() const { return QString(name()); }
      void dumpQPointF(const char*) const;

      virtual Space space() const      { return Space(0.0, width()); }

      virtual QColor color() const             { return _color; }
      QColor curColor() const;
      QColor curColor(const Element* proxy) const;
      virtual void setColor(const QColor& c)     { _color = c;    }
      void undoSetColor(const QColor& c);
      void undoSetVisible(bool v);

      static Element::Type readType(XmlReader& node, QPointF*, Fraction*);

      QByteArray mimeData(const QPointF&) const;
/**
 Return true if this element accepts a drop at canvas relative \a pos
 of given element \a type and \a subtype.

 Reimplemented by elements that accept drops. Used to change cursor shape while
 dragging to indicate drop targets.
*/
      virtual bool acceptDrop(const DropData&) const { return false; }

/**
 Handle a dropped element at canvas relative \a pos of given element
 \a type and \a subtype. Returns dropped element if any.
 The ownership of element in DropData is transfered to the called
 element (if not used, element has to be deleted).
 The returned element will be selected if not in note edit mode.

 Reimplemented by elements that accept drops.
*/
      virtual Element* drop(const DropData&) { return 0;}

/**
 delivers mouseEvent to element in edit mode
 returns true if mouse event is accepted by element
 */
      virtual bool mousePress(const QPointF&, QMouseEvent*) { return false; }

      mutable bool itemDiscovered;     ///< helper flag for bsp

      virtual void scanElements(void* data, void (*func)(void*, Element*), bool all=true);

      virtual void reset();

      virtual qreal mag() const        { return _mag;   }
      void setMag(qreal val)           { _mag = val;    }
      qreal magS() const;

      bool isText() const;
      bool isPrintable() const;
      virtual bool isSpanner() const           { return false; }
      virtual bool isSpannerSegment() const    { return false; }

      qreal point(const Spatium sp) const { return sp.val() * spatium(); }

      //
      // check element for consistency; return false if element
      // is not valid
      //
      virtual bool check() const { return true; }

      QPointF startDragPosition() const           { return _startDragPosition; }
      void setStartDragPosition(const QPointF& v) { _startDragPosition = v; }

      static const char* name(Element::Type type);
      static Ms::Element* create(Ms::Element::Type type, Score*);
      static Element::Type name2type(const QStringRef&);
      static Element* name2Element(const QStringRef&, Score*);

      void setFlag(ElementFlag f, bool v)  {
            if (v)
                  _flags |= f;
            else
                  _flags &= ~ElementFlags(f);
            }
      bool flag(ElementFlag f) const   { return _flags & f; }
      void setFlags(ElementFlags f)    { _flags = f;    }
      ElementFlags flags() const       { return _flags; }
      virtual bool systemFlag() const  { return false;  }
      bool selectable() const          { return flag(ElementFlag::SELECTABLE);  }
      void setSelectable(bool val)     { setFlag(ElementFlag::SELECTABLE, val); }
      bool dropTarget() const          { return flag(ElementFlag::DROP_TARGET); }
      void setDropTarget(bool v) const {
            if (v)
                  _flags |= ElementFlag::DROP_TARGET;
            else
                  _flags &= ~ElementFlags(ElementFlag::DROP_TARGET);
            }
      virtual bool isMovable() const   { return flag(ElementFlag::MOVABLE);     }
      bool isSegment() const           { return flag(ElementFlag::SEGMENT);     }
      uint tag() const                 { return _tag;                      }
      void setTag(uint val)            { _tag = val;                       }

      virtual QVariant getProperty(P_ID) const override;
      virtual bool setProperty(P_ID, const QVariant&) override;
      virtual QVariant propertyDefault(P_ID) const override;

      virtual void styleChanged() {}

      void drawSymbol(SymId id, QPainter* p, const QPointF& o = QPointF()) const;
      void drawSymbol(SymId id, QPainter* p, const QPointF& o, int n) const;
      void drawSymbols(const QList<SymId>&, QPainter* p, const QPointF& o = QPointF()) const;
      qreal symHeight(SymId id) const;
      qreal symWidth(SymId id) const;
      qreal symWidth(const QList<SymId>&) const;
      QRectF symBbox(SymId id) const;
      QRectF symBbox(const QList<SymId>&) const;
      QPointF symStemDownNW(SymId id) const;
      QPointF symStemUpSE(SymId id) const;
      QPointF symCutOutNE(SymId id) const;
      QPointF symCutOutNW(SymId id) const;
      QPointF symCutOutSE(SymId id) const;
      QPointF symCutOutSW(SymId id) const;
      qreal symAdvance(SymId id) const;
      QList<SymId> toTimeSigString(const QString& s) const;
      bool symIsValid(SymId id) const;

      virtual Element* nextElement();  //< Used for navigation
      virtual Element* prevElement();  //< next-element and prev-element command

      bool concertPitch() const;
      virtual QString accessibleInfo();                                  //< used to populate the status bar
      virtual QString screenReaderInfo()    { return accessibleInfo(); } //< by default returns accessibleInfo, but can be overriden
                                                                         //  if the screen-reader needs a special string (see note for example)
      virtual QString accessibleExtraInfo() { return QString();        } //< used to return info that will be appended to accessibleInfo
                                                                         // and passed only to the screen-reader

      virtual bool isUserModified() const;
      };

//---------------------------------------------------------
//   ElementList
//---------------------------------------------------------

// class ElementList : public std::list<Element*> {
class ElementList : public QList<Element*> {
   public:
      ElementList() {}
      bool remove(Element*);
      void replace(Element* old, Element* n);
      void write(Xml&) const;
      void write(Xml&, const char* name) const;
      };

//-------------------------------------------------------------------
//   @@ StaffLines
///    The StaffLines class is the graphic representation of a staff,
///    it draws the horizontal staff lines.
//-------------------------------------------------------------------

class StaffLines : public Element {
      Q_OBJECT

      qreal dist;
      qreal lw;
      int lines;

   public:
      StaffLines(Score*);
      virtual StaffLines* clone() const    { return new StaffLines(*this); }
      virtual Element::Type type() const   { return Element::Type::STAFF_LINES; }
      virtual void layout();

      Measure* measure() const             { return (Measure*)parent(); }
      virtual void draw(QPainter*) const;
      virtual QPointF pagePos() const;    ///< position in page coordinates
      virtual QPointF canvasPos() const;  ///< position in page coordinates
      qreal y1() const;
      qreal staffHeight() const { return (lines-1) * dist; }
      };

//---------------------------------------------------------
//   @@ Line
//---------------------------------------------------------

class Line : public Element {
      Q_OBJECT

      Spatium _width;
      Spatium _len;
      int _z;                     ///< stacking order when drawing or selecting;
                                  ///< elements are drawn from high number to low number;
                                  ///< default is type() * 100;

   protected:
      bool vertical;

   public:
      Line(Score*);
      Line(Score*, bool vertical);
      Line &operator=(const Line&);

      virtual Line* clone() const        { return new Line(*this); }
      virtual Element::Type type() const { return Element::Type::LINE; }
      virtual void layout();

      virtual void draw(QPainter*) const;
      void writeProperties(Xml& xml) const;
      bool readProperties(XmlReader&);
      void dump() const;

      Spatium len()    const { return _len; }
      Spatium lineWidth()  const { return _width; }
      void setLen(Spatium);
      void setLineWidth(Spatium);
      virtual int z() const               { return _z; }
      void setZ(int val)                  { _z = val;  }
      };

//---------------------------------------------------------
//   @@ Compound
//---------------------------------------------------------

class Compound : public Element {
      Q_OBJECT

      QList<Element*> elements;

   protected:
      const QList<Element*>& getElements() const { return elements; }

   public:
      Compound(Score*);
      Compound(const Compound&);
      virtual Element::Type type() const = 0;

      virtual void draw(QPainter*) const;
      virtual void addElement(Element*, qreal x, qreal y);
      void clear();
      virtual void setSelected(bool f);
      virtual void setVisible(bool);
      virtual void layout();
      };

extern bool elementLessThan(const Element* const, const Element* const);
extern void collectElements(void* data, Element* e);


}     // namespace Ms



Q_DECLARE_METATYPE(Ms::Element::Type);
Q_DECLARE_METATYPE(Ms::Element::Placement);

#endif