1f9ccfcdce
git-subtree-dir: libmscore git-subtree-mainline:412ca45401
git-subtree-split:6047361bd0
1666 lines
52 KiB
C++
1666 lines
52 KiB
C++
//=============================================================================
|
|
// MuseScore
|
|
// Music Composition & Notation
|
|
// $Id: element.cpp 5629 2012-05-15 12:38:33Z wschweer $
|
|
//
|
|
// Copyright (C) 2002-2011 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
|
|
//=============================================================================
|
|
|
|
/**
|
|
\file
|
|
Implementation of Element, ElementList, StaffLines.
|
|
*/
|
|
|
|
#include "element.h"
|
|
#include "style.h"
|
|
#include "xml.h"
|
|
#include "score.h"
|
|
#include "staff.h"
|
|
#include "utils.h"
|
|
#include "sym.h"
|
|
#include "symbol.h"
|
|
#include "clef.h"
|
|
#include "volta.h"
|
|
#include "ottava.h"
|
|
#include "textline.h"
|
|
#include "trill.h"
|
|
#include "pedal.h"
|
|
#include "hairpin.h"
|
|
#include "keysig.h"
|
|
#include "timesig.h"
|
|
#include "barline.h"
|
|
#include "arpeggio.h"
|
|
#include "breath.h"
|
|
#include "bracket.h"
|
|
#include "chordrest.h"
|
|
#include "accidental.h"
|
|
#include "dynamic.h"
|
|
#include "text.h"
|
|
#include "note.h"
|
|
#include "tremolo.h"
|
|
#include "layoutbreak.h"
|
|
#include "repeat.h"
|
|
#include "page.h"
|
|
#include "system.h"
|
|
#include "stafftext.h"
|
|
#include "glissando.h"
|
|
#include "articulation.h"
|
|
#include "chord.h"
|
|
#include "spacer.h"
|
|
#include "tempotext.h"
|
|
#include "harmony.h"
|
|
#include "lyrics.h"
|
|
#include "rest.h"
|
|
#include "slur.h"
|
|
#include "measure.h"
|
|
#include "fret.h"
|
|
#include "staffstate.h"
|
|
#include "fingering.h"
|
|
#include "bend.h"
|
|
#include "tremolobar.h"
|
|
#include "chordline.h"
|
|
#include "undo.h"
|
|
#include "segment.h"
|
|
#include "box.h"
|
|
#include "instrchange.h"
|
|
#include "stafftype.h"
|
|
#include "stem.h"
|
|
#include "iname.h"
|
|
#include "mscore.h"
|
|
#include "icon.h"
|
|
#include "ossia.h"
|
|
#include "figuredbass.h"
|
|
#include "rehearsalmark.h"
|
|
#include "notedot.h"
|
|
|
|
extern bool showInvisible;
|
|
|
|
//
|
|
// list has to be synchronized with ElementType enum
|
|
//
|
|
static const char* elementNames[] = {
|
|
QT_TRANSLATE_NOOP("elementName", "invalid"),
|
|
QT_TRANSLATE_NOOP("elementName", "Symbol"),
|
|
QT_TRANSLATE_NOOP("elementName", "Text"),
|
|
QT_TRANSLATE_NOOP("elementName", "InstrumentName"),
|
|
QT_TRANSLATE_NOOP("elementName", "SlurSegment"),
|
|
QT_TRANSLATE_NOOP("elementName", "BarLine"),
|
|
QT_TRANSLATE_NOOP("elementName", "StemSlash"),
|
|
QT_TRANSLATE_NOOP("elementName", "Line"),
|
|
QT_TRANSLATE_NOOP("elementName", "Bracket"),
|
|
QT_TRANSLATE_NOOP("elementName", "Arpeggio"),
|
|
QT_TRANSLATE_NOOP("elementName", "Accidental"),
|
|
QT_TRANSLATE_NOOP("elementName", "Note"),
|
|
QT_TRANSLATE_NOOP("elementName", "Stem"), // 10
|
|
QT_TRANSLATE_NOOP("elementName", "Clef"),
|
|
QT_TRANSLATE_NOOP("elementName", "KeySig"),
|
|
QT_TRANSLATE_NOOP("elementName", "TimeSig"),
|
|
QT_TRANSLATE_NOOP("elementName", "Rest"),
|
|
QT_TRANSLATE_NOOP("elementName", "Breath"),
|
|
QT_TRANSLATE_NOOP("elementName", "Glissando"),
|
|
QT_TRANSLATE_NOOP("elementName", "RepeatMeasure"),
|
|
QT_TRANSLATE_NOOP("elementName", "Image"),
|
|
QT_TRANSLATE_NOOP("elementName", "Tie"),
|
|
QT_TRANSLATE_NOOP("elementName", "Articulation"), // 20
|
|
QT_TRANSLATE_NOOP("elementName", "ChordLine"),
|
|
QT_TRANSLATE_NOOP("elementName", "Dynamic"),
|
|
QT_TRANSLATE_NOOP("elementName", "Beam"),
|
|
QT_TRANSLATE_NOOP("elementName", "Hook"),
|
|
QT_TRANSLATE_NOOP("elementName", "Lyrics"),
|
|
QT_TRANSLATE_NOOP("elementName", "FiguredBass"),
|
|
QT_TRANSLATE_NOOP("elementName", "Marker"),
|
|
QT_TRANSLATE_NOOP("elementName", "Jump"),
|
|
QT_TRANSLATE_NOOP("elementName", "Fingering"),
|
|
QT_TRANSLATE_NOOP("elementName", "Tuplet"),
|
|
QT_TRANSLATE_NOOP("elementName", "Tempo"),
|
|
QT_TRANSLATE_NOOP("elementName", "StaffText"),
|
|
QT_TRANSLATE_NOOP("elementName", "RehearsalMark"),
|
|
QT_TRANSLATE_NOOP("elementName", "InstrumentChange"),
|
|
QT_TRANSLATE_NOOP("elementName", "Harmony"),
|
|
QT_TRANSLATE_NOOP("elementName", "FretDiagram"),
|
|
QT_TRANSLATE_NOOP("elementName", "Bend"),
|
|
QT_TRANSLATE_NOOP("elementName", "TremoloBar"),
|
|
QT_TRANSLATE_NOOP("elementName", "Volta"),
|
|
QT_TRANSLATE_NOOP("elementName", "HairpinSegment"),
|
|
QT_TRANSLATE_NOOP("elementName", "OttavaSegment"),
|
|
QT_TRANSLATE_NOOP("elementName", "TrillSegment"),
|
|
QT_TRANSLATE_NOOP("elementName", "TextLineSegment"),
|
|
QT_TRANSLATE_NOOP("elementName", "VoltaSegment"),
|
|
QT_TRANSLATE_NOOP("elementName", "LayoutBreak"),
|
|
QT_TRANSLATE_NOOP("elementName", "Spacer"),
|
|
QT_TRANSLATE_NOOP("elementName", "StaffState"),
|
|
QT_TRANSLATE_NOOP("elementName", "LedgerLine"),
|
|
QT_TRANSLATE_NOOP("elementName", "NoteHead"),
|
|
QT_TRANSLATE_NOOP("elementName", "NoteDot"),
|
|
QT_TRANSLATE_NOOP("elementName", "Tremolo"),
|
|
QT_TRANSLATE_NOOP("elementName", "Measure"),
|
|
QT_TRANSLATE_NOOP("elementName", "StaffLines"),
|
|
QT_TRANSLATE_NOOP("elementName", "Selection"),
|
|
QT_TRANSLATE_NOOP("elementName", "Lasso"),
|
|
QT_TRANSLATE_NOOP("elementName", "ShadowNote"),
|
|
QT_TRANSLATE_NOOP("elementName", "RubberBand"),
|
|
QT_TRANSLATE_NOOP("elementName", "TabDurationSymbol"),
|
|
QT_TRANSLATE_NOOP("elementName", "FSymbol"),
|
|
QT_TRANSLATE_NOOP("elementName", "Page"),
|
|
QT_TRANSLATE_NOOP("elementName", "HairPin"),
|
|
QT_TRANSLATE_NOOP("elementName", "Ottava"),
|
|
QT_TRANSLATE_NOOP("elementName", "Pedal"),
|
|
QT_TRANSLATE_NOOP("elementName", "Trill"),
|
|
QT_TRANSLATE_NOOP("elementName", "TextLine"),
|
|
QT_TRANSLATE_NOOP("elementName", "Segment"),
|
|
QT_TRANSLATE_NOOP("elementName", "System"),
|
|
QT_TRANSLATE_NOOP("elementName", "Compound"),
|
|
QT_TRANSLATE_NOOP("elementName", "Chord"),
|
|
QT_TRANSLATE_NOOP("elementName", "Slur"),
|
|
QT_TRANSLATE_NOOP("elementName", "Element"),
|
|
QT_TRANSLATE_NOOP("elementName", "ElementList"),
|
|
QT_TRANSLATE_NOOP("elementName", "StaffList"),
|
|
QT_TRANSLATE_NOOP("elementName", "MeasureList"),
|
|
QT_TRANSLATE_NOOP("elementName", "Layout"),
|
|
QT_TRANSLATE_NOOP("elementName", "HBox"),
|
|
QT_TRANSLATE_NOOP("elementName", "VBox"),
|
|
QT_TRANSLATE_NOOP("elementName", "TBox"),
|
|
QT_TRANSLATE_NOOP("elementName", "FBox"),
|
|
QT_TRANSLATE_NOOP("elementName", "AccidentalBracket"),
|
|
QT_TRANSLATE_NOOP("elementName", "Icon"),
|
|
QT_TRANSLATE_NOOP("elementName", "Ossia")
|
|
};
|
|
|
|
static bool defaultVisible = true;
|
|
static bool defaultSelected = false;
|
|
|
|
//---------------------------------------------------------
|
|
// DropData
|
|
//---------------------------------------------------------
|
|
|
|
DropData::DropData()
|
|
{
|
|
view = 0;
|
|
element = 0;
|
|
duration = Fraction(1,4);
|
|
modifiers = 0;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// propertyList
|
|
//---------------------------------------------------------
|
|
|
|
Property<Element> Element::propertyList[] = {
|
|
{ P_COLOR, &Element::pColor, &MScore::defaultColor },
|
|
{ P_VISIBLE, &Element::pVisible, &defaultVisible },
|
|
{ P_SELECTED, &Element::pSelected, &defaultSelected },
|
|
// not written:
|
|
{ P_USER_OFF, &Element::pUserOff, 0 },
|
|
{ P_END, 0, 0 }
|
|
};
|
|
|
|
//---------------------------------------------------------
|
|
// LinkedElements
|
|
//---------------------------------------------------------
|
|
|
|
LinkedElements::LinkedElements(Score* score)
|
|
{
|
|
_lid = score->linkId(); // create new unique id
|
|
}
|
|
|
|
LinkedElements::LinkedElements(Score* score, int id)
|
|
{
|
|
_lid = id;
|
|
score->linkId(id);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setLid
|
|
//---------------------------------------------------------
|
|
|
|
void LinkedElements::setLid(Score* score, int id)
|
|
{
|
|
_lid = id;
|
|
score->linkId(id);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// spatiumChanged
|
|
//---------------------------------------------------------
|
|
|
|
void Element::spatiumChanged(qreal oldValue, qreal newValue)
|
|
{
|
|
_userOff *= (newValue / oldValue);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// spatium
|
|
//---------------------------------------------------------
|
|
|
|
qreal Element::spatium() const
|
|
{
|
|
Staff* s = staff();
|
|
qreal v = _score->spatium();
|
|
return s ? v * s->mag() : v;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// magS
|
|
//---------------------------------------------------------
|
|
|
|
qreal Element::magS() const
|
|
{
|
|
return _mag * (_score->spatium() /(MScore::DPI * SPATIUM20));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// name
|
|
//---------------------------------------------------------
|
|
|
|
const char* Element::name() const
|
|
{
|
|
return name(type());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// userName
|
|
//---------------------------------------------------------
|
|
|
|
QString Element::userName() const
|
|
{
|
|
return qApp->translate("elementName", name(type()));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// ~Element
|
|
//---------------------------------------------------------
|
|
|
|
Element::~Element()
|
|
{
|
|
if (_links) {
|
|
_links->removeOne(this);
|
|
if (_links->isEmpty()) {
|
|
//DEBUG:
|
|
score()->links().remove(_links->lid());
|
|
//
|
|
delete _links;
|
|
}
|
|
}
|
|
if (score()) {
|
|
foreach(Element* e, score()->selection().elements()) {
|
|
if (e == this) {
|
|
// if (MScore::debugMode)
|
|
qDebug("======~Element: %p still in selection! generated %d\n",
|
|
this, generated());
|
|
// if (MScore::debugMode)
|
|
// abort();
|
|
score()->deselect(this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// Element
|
|
//---------------------------------------------------------
|
|
|
|
Element::Element(Score* s) :
|
|
_links(0),
|
|
_parent(0),
|
|
_selected(false),
|
|
_generated(false),
|
|
_visible(true),
|
|
_flags(ELEMENT_SELECTABLE),
|
|
_track(-1),
|
|
_color(MScore::defaultColor),
|
|
_mag(1.0),
|
|
_tag(1),
|
|
_score(s),
|
|
_mxmlOff(0),
|
|
itemDiscovered(0)
|
|
{
|
|
}
|
|
|
|
Element::Element(const Element& e)
|
|
{
|
|
_links = 0;
|
|
_parent = e._parent;
|
|
_selected = e._selected;
|
|
_generated = e._generated;
|
|
_visible = e._visible;
|
|
_flags = e._flags;
|
|
_track = e._track;
|
|
_color = e._color;
|
|
_mag = e._mag;
|
|
_pos = e._pos;
|
|
_userOff = e._userOff;
|
|
_readPos = e._readPos;
|
|
_score = e._score;
|
|
_mxmlOff = e._mxmlOff;
|
|
_bbox = e._bbox;
|
|
_tag = e._tag;
|
|
itemDiscovered = 0;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// linkTo
|
|
//---------------------------------------------------------
|
|
|
|
void Element::linkTo(Element* element)
|
|
{
|
|
Q_ASSERT(!_links || !element->links() | (_links == element->links()));
|
|
if (!_links) {
|
|
if (element->links()) {
|
|
_links = element->links();
|
|
Q_ASSERT(_links->contains(element));
|
|
}
|
|
else {
|
|
_links = new LinkedElements(score());
|
|
_links->append(element);
|
|
element->setLinks(_links);
|
|
}
|
|
_links->append(this);
|
|
}
|
|
else {
|
|
Q_ASSERT(_links->contains(this));
|
|
_links->append(element);
|
|
element->setLinks(_links);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// linkedClone
|
|
//---------------------------------------------------------
|
|
|
|
Element* Element::linkedClone()
|
|
{
|
|
Element* e = clone();
|
|
linkTo(e);
|
|
return e;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// linkList
|
|
//---------------------------------------------------------
|
|
|
|
QList<Element*> Element::linkList() const
|
|
{
|
|
QList<Element*> el;
|
|
if (links())
|
|
el.append(*links());
|
|
else
|
|
el.append((Element*)this);
|
|
return el;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// adjustReadPos
|
|
//---------------------------------------------------------
|
|
|
|
void Element::adjustReadPos()
|
|
{
|
|
if (!_readPos.isNull()) {
|
|
_userOff = _readPos - _pos;
|
|
_readPos = QPointF();
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// scanElements
|
|
//---------------------------------------------------------
|
|
|
|
void Element::scanElements(void* data, void (*func)(void*, Element*), bool all)
|
|
{
|
|
if (all || _visible || score()->showInvisible())
|
|
func(data, this);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// toDefault
|
|
//---------------------------------------------------------
|
|
|
|
void Element::toDefault()
|
|
{
|
|
if (!_userOff.isNull())
|
|
score()->undoChangeUserOffset(this, QPointF());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// change
|
|
//---------------------------------------------------------
|
|
|
|
void Element::change(Element* o, Element* n)
|
|
{
|
|
remove(o);
|
|
add(n);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// staff
|
|
//---------------------------------------------------------
|
|
|
|
Staff* Element::staff() const
|
|
{
|
|
if (_track == -1)
|
|
return 0;
|
|
return score()->staff(staffIdx());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// curColor
|
|
//---------------------------------------------------------
|
|
|
|
QColor Element::curColor() const
|
|
{
|
|
// the default element color is always interpreted as black in
|
|
// printing
|
|
if (score() && score()->printing())
|
|
return (_color == MScore::defaultColor) ? Qt::black : _color;
|
|
|
|
if (flag(ELEMENT_DROP_TARGET))
|
|
return MScore::dropColor;
|
|
if (_selected) {
|
|
if (track() == -1)
|
|
return MScore::selectColor[0];
|
|
else
|
|
return MScore::selectColor[voice()];
|
|
}
|
|
if (!_visible)
|
|
return Qt::gray;
|
|
return _color;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// drag
|
|
//---------------------------------------------------------
|
|
|
|
/**
|
|
Return update Rect relative to canvas.
|
|
*/
|
|
|
|
QRectF Element::drag(const EditData& data)
|
|
{
|
|
QRectF r(canvasBoundingRect());
|
|
|
|
qreal x = data.pos.x();
|
|
qreal y = data.pos.y();
|
|
|
|
qreal _spatium = spatium();
|
|
if (data.hRaster) {
|
|
qreal hRaster = _spatium / MScore::hRaster();
|
|
int n = lrint(x / hRaster);
|
|
x = hRaster * n;
|
|
}
|
|
if (data.vRaster) {
|
|
qreal vRaster = _spatium / MScore::vRaster();
|
|
int n = lrint(y / vRaster);
|
|
y = vRaster * n;
|
|
}
|
|
setUserOff(QPointF(x, y));
|
|
return canvasBoundingRect() | r;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// pagePos
|
|
// return position in canvas coordinates
|
|
//---------------------------------------------------------
|
|
|
|
QPointF Element::pagePos() const
|
|
{
|
|
QPointF p(pos());
|
|
if (parent() == 0)
|
|
return p;
|
|
|
|
if (_flags & ELEMENT_ON_STAFF) {
|
|
System* system = static_cast<Segment*>(parent())->measure()->system();
|
|
if (system) {
|
|
int si = staffIdx();
|
|
if (type() == CHORD || type() == REST)
|
|
si += static_cast<const ChordRest*>(this)->staffMove();
|
|
p.ry() += system->staff(si)->y() + system->y();
|
|
}
|
|
p.rx() = pageX();
|
|
}
|
|
else {
|
|
if (parent() && parent()->parent())
|
|
p += parent()->pagePos();
|
|
}
|
|
return p;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// canvasPos
|
|
//---------------------------------------------------------
|
|
|
|
QPointF Element::canvasPos() const
|
|
{
|
|
QPointF p(pos());
|
|
if (parent() == 0)
|
|
return p;
|
|
if (_flags & ELEMENT_ON_STAFF) {
|
|
System* system = static_cast<Segment*>(parent())->measure()->system();
|
|
if (system) {
|
|
int si = staffIdx();
|
|
if (type() == CHORD || type() == REST)
|
|
si += static_cast<const ChordRest*>(this)->staffMove();
|
|
p.ry() += system->staff(si)->y() + system->y();
|
|
Page* page = system->page();
|
|
if (page)
|
|
p.ry() += page->y();
|
|
}
|
|
p.rx() = canvasX();
|
|
}
|
|
else {
|
|
if (parent())
|
|
p += parent()->canvasPos();
|
|
}
|
|
return p;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// pageX
|
|
//---------------------------------------------------------
|
|
|
|
qreal Element::pageX() const
|
|
{
|
|
qreal xp = x();
|
|
for (Element* e = parent(); e && e->parent(); e = e->parent())
|
|
xp += e->x();
|
|
return xp;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// canvasX
|
|
//---------------------------------------------------------
|
|
|
|
qreal Element::canvasX() const
|
|
{
|
|
qreal xp = x();
|
|
for (Element* e = parent(); e; e = e->parent())
|
|
xp += e->x();
|
|
return xp;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// contains
|
|
//---------------------------------------------------------
|
|
|
|
/**
|
|
Return true if \a p is inside the shape of the object.
|
|
|
|
Note: \a p is in page coordinates
|
|
*/
|
|
|
|
bool Element::contains(const QPointF& p) const
|
|
{
|
|
return shape().contains(p - pagePos());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// shape
|
|
//---------------------------------------------------------
|
|
|
|
/**
|
|
Returns the shape of this element as a QPainterPath in local
|
|
coordinates. The shape is used for collision detection and
|
|
hit tests (contains())
|
|
|
|
The default implementation calls bbox() to return a simple rectangular
|
|
shape, but subclasses can reimplement this function to return a more
|
|
accurate shape for non-rectangular elements.
|
|
*/
|
|
|
|
QPainterPath Element::shape() const
|
|
{
|
|
QPainterPath pp;
|
|
pp.addRect(bbox());
|
|
return pp;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// intersects
|
|
//---------------------------------------------------------
|
|
|
|
/**
|
|
Return true if \a rr intersects bounding box of object.
|
|
|
|
Note: \a rr is in page coordinates
|
|
*/
|
|
|
|
bool Element::intersects(const QRectF& rr) const
|
|
{
|
|
return shape().intersects(rr.translated(-pagePos()));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// writeProperties
|
|
//---------------------------------------------------------
|
|
|
|
void Element::writeProperties(Xml& xml) const
|
|
{
|
|
if (_links && (_links->size() > 1))
|
|
xml.tag("lid", _links->lid());
|
|
if (!userOff().isNull()) {
|
|
if (type() == VOLTA_SEGMENT)
|
|
xml.tag("offset", userOff() / spatium());
|
|
else
|
|
xml.tag("pos", pos() / spatium());
|
|
}
|
|
if ((track() != xml.curTrack) && (track() != -1)) {
|
|
int t;
|
|
t = track() + xml.trackDiff;
|
|
xml.tag("track", t);
|
|
}
|
|
if (_tag != 0x1) {
|
|
for (int i = 1; i < MAX_TAGS; i++) {
|
|
if (_tag == ((unsigned)1 << i)) {
|
|
xml.tag("tag", score()->layerTags()[i]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (color() != Qt::black)
|
|
xml.tag("color", color());
|
|
if (!visible())
|
|
xml.tag("visible", visible());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// readProperties
|
|
//---------------------------------------------------------
|
|
|
|
bool Element::readProperties(const QDomElement& e)
|
|
{
|
|
const QString& tag(e.tagName());
|
|
const QString& val(e.text());
|
|
|
|
if (setProperty(tag, e))
|
|
;
|
|
else if (tag == "lid") {
|
|
_links = score()->links().value(val.toInt());
|
|
if (!_links) {
|
|
int i = val.toInt();
|
|
if (score()->parentScore()) // DEBUG
|
|
qDebug("---link %d not found (%d)\n", i, score()->links().size());
|
|
_links = new LinkedElements(score(), i);
|
|
score()->links().insert(i, _links);
|
|
}
|
|
_links->append(this);
|
|
}
|
|
else if (tag == "tick")
|
|
score()->curTick = score()->fileDivision(val.toInt());
|
|
else if (tag == "offset") { // ??obsolete -> used for volta
|
|
qreal _spatium = spatium();
|
|
QPointF pt(readPoint(e) * _spatium);
|
|
setUserOff(pt);
|
|
_readPos = QPointF();
|
|
}
|
|
else if (tag == "pos") {
|
|
qreal _spatium = spatium();
|
|
setUserOff(QPointF());
|
|
_readPos = readPoint(e) * _spatium;
|
|
}
|
|
else if (tag == "voice")
|
|
setTrack((_track/VOICES)*VOICES + val.toInt());
|
|
else if (tag == "track")
|
|
setTrack(val.toInt());
|
|
/* else if (tag == "systemFlag") {
|
|
int i = val.toInt();
|
|
setFlag(ELEMENT_SYSTEM_FLAG, i);
|
|
if (i)
|
|
_track = 0;
|
|
}
|
|
*/
|
|
else if (tag == "tag") {
|
|
for (int i = 1; i < MAX_TAGS; i++) {
|
|
if (score()->layerTags()[i] == val) {
|
|
_tag = 1 << i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// write
|
|
//---------------------------------------------------------
|
|
|
|
void Element::write(Xml& xml) const
|
|
{
|
|
xml.stag(name());
|
|
Element::writeProperties(xml);
|
|
xml.etag();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// read
|
|
//---------------------------------------------------------
|
|
|
|
void Element::read(const QDomElement& de)
|
|
{
|
|
for (QDomElement e = de.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) {
|
|
if (!Element::readProperties(e))
|
|
domError(e);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// remove
|
|
//---------------------------------------------------------
|
|
|
|
/**
|
|
Remove \a el from the list. Return true on success.
|
|
*/
|
|
|
|
bool ElementList::remove(Element* el)
|
|
{
|
|
int idx = indexOf(el);
|
|
if (idx == -1)
|
|
return false;
|
|
removeAt(idx);
|
|
return true;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// replace
|
|
//---------------------------------------------------------
|
|
|
|
void ElementList::replace(Element* o, Element* n)
|
|
{
|
|
int idx = indexOf(o);
|
|
if (idx == -1) {
|
|
qDebug("ElementList::replace: element not found\n");
|
|
return;
|
|
}
|
|
QList<Element*>::replace(idx, n);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// write
|
|
//---------------------------------------------------------
|
|
|
|
void ElementList::write(Xml& xml) const
|
|
{
|
|
for (ciElement ie = begin(); ie != end(); ++ie)
|
|
(*ie)->write(xml);
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------
|
|
// StaffLines
|
|
//---------------------------------------------------------
|
|
|
|
StaffLines::StaffLines(Score* s)
|
|
: Element(s)
|
|
{
|
|
setWidth(1.0); // dummy
|
|
lines = 5;
|
|
setSelectable(false);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// pagePos
|
|
//---------------------------------------------------------
|
|
|
|
QPointF StaffLines::pagePos() const
|
|
{
|
|
System* system = measure()->system();
|
|
return QPointF(measure()->x() + system->x(),
|
|
system->staff(staffIdx())->y() + system->y());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// layout
|
|
//---------------------------------------------------------
|
|
|
|
void StaffLines::layout()
|
|
{
|
|
StaffType* st = staff() ? staff()->staffType() : 0;
|
|
qreal _spatium = spatium();
|
|
if (st) {
|
|
dist = st->lineDistance().val() * _spatium;
|
|
lines = st->lines();
|
|
}
|
|
else {
|
|
dist = _spatium;
|
|
lines = 5;
|
|
}
|
|
|
|
// qDebug("StaffLines::layout:: dist %f st %p\n", dist, st);
|
|
|
|
lw = score()->styleS(ST_staffLineWidth).val() * _spatium;
|
|
|
|
qreal w = width();
|
|
switch (lines) {
|
|
case 0:
|
|
setbbox(QRectF(0.0, - 2.0 * dist - lw*.5, w, 4 * dist + lw));
|
|
break;
|
|
case 1:
|
|
setbbox(QRectF(0.0, -lw*.5, w, lw));
|
|
break;
|
|
case 2:
|
|
setbbox(QRectF(0.0, -lw*.5, w, lines * dist + lw));
|
|
break;
|
|
default:
|
|
setbbox(QRectF(0.0, -lw*.5, w, lines * dist + lw));
|
|
break;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// draw
|
|
//---------------------------------------------------------
|
|
|
|
void StaffLines::draw(QPainter* painter) const
|
|
{
|
|
QPointF _pos(0.0, 0.0);
|
|
|
|
qreal x1 = _pos.x();
|
|
qreal x2 = x1 + width();
|
|
|
|
QVector<QLineF> ll(lines);
|
|
qreal y = _pos.y();
|
|
for (int i = 0; i < lines; ++i) {
|
|
ll[i].setLine(x1, y, x2, y);
|
|
y += dist;
|
|
}
|
|
if (MScore::debugMode) {
|
|
painter->setPen(QPen(Qt::lightGray, lw, Qt::SolidLine, Qt::FlatCap));
|
|
y = _pos.y() - 3 * dist;
|
|
painter->drawLine(QLineF(x1, y, x2, y));
|
|
y = _pos.y() - 2 * dist;
|
|
painter->drawLine(QLineF(x1, y, x2, y));
|
|
y = _pos.y() - dist;
|
|
painter->drawLine(QLineF(x1, y, x2, y));
|
|
y = _pos.y() + lines * dist;
|
|
painter->drawLine(QLineF(x1, y, x2, y));
|
|
y = _pos.y() + (lines+1) * dist;
|
|
painter->drawLine(QLineF(x1, y, x2, y));
|
|
y = _pos.y() + (lines+2) * dist;
|
|
painter->drawLine(QLineF(x1, y, x2, y));
|
|
}
|
|
painter->setPen(QPen(curColor(), lw, Qt::SolidLine, Qt::FlatCap));
|
|
painter->drawLines(ll);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// y1
|
|
//---------------------------------------------------------
|
|
|
|
qreal StaffLines::y1() const
|
|
{
|
|
System* system = measure()->system();
|
|
if (system == 0)
|
|
return 0.0;
|
|
|
|
qreal y = system->staff(staffIdx())->y() + ipos().y();
|
|
|
|
switch (lines) {
|
|
case 1:
|
|
return y - spatium();
|
|
default:
|
|
return y;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// y2
|
|
//---------------------------------------------------------
|
|
|
|
qreal StaffLines::y2() const
|
|
{
|
|
System* system = measure()->system();
|
|
if (system == 0)
|
|
return 0.0;
|
|
|
|
qreal y = system->staff(staffIdx())->y() + ipos().y();
|
|
|
|
switch (lines) {
|
|
case 1:
|
|
return y + spatium();
|
|
default:
|
|
return y + (lines - 1) * dist;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// Line
|
|
//---------------------------------------------------------
|
|
|
|
Line::Line(Score* s, bool v)
|
|
: Element(s)
|
|
{
|
|
vertical = v;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// dump
|
|
//---------------------------------------------------------
|
|
|
|
void Line::dump() const
|
|
{
|
|
qDebug(" width:%g height:%g vert:%d\n", point(_width), point(_len), vertical);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setLen
|
|
//---------------------------------------------------------
|
|
|
|
void Line::setLen(Spatium l)
|
|
{
|
|
_len = l;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setLineWidth
|
|
//---------------------------------------------------------
|
|
|
|
void Line::setLineWidth(Spatium w)
|
|
{
|
|
_width = w;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// layout
|
|
//---------------------------------------------------------
|
|
|
|
void Line::layout()
|
|
{
|
|
qreal sp = spatium();
|
|
qreal w = _width.val() * sp;
|
|
qreal l = _len.val() * sp;
|
|
qreal w2 = w * .5;
|
|
if (vertical)
|
|
setbbox(QRectF(-w2, -w2, w, l + w));
|
|
else
|
|
setbbox(QRectF(-w2, -w2, l + w, w));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// draw
|
|
//---------------------------------------------------------
|
|
|
|
void Line::draw(QPainter* painter) const
|
|
{
|
|
qreal sp = spatium();
|
|
painter->setPen(QPen(curColor(), _width.val() * sp));
|
|
|
|
qreal l = _len.val() * sp;
|
|
if (vertical)
|
|
painter->drawLine(QLineF(0.0, 0.0, 0.0, l));
|
|
else
|
|
painter->drawLine(QLineF(0.0, 0.0, l, 0.0));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// writeProperties
|
|
//---------------------------------------------------------
|
|
|
|
void Line::writeProperties(Xml& xml) const
|
|
{
|
|
xml.tag("lineWidth", _width.val());
|
|
xml.tag("lineLen", _len.val());
|
|
if (!vertical)
|
|
xml.tag("vertical", vertical);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// readProperties
|
|
//---------------------------------------------------------
|
|
|
|
bool Line::readProperties(const QDomElement& e)
|
|
{
|
|
const QString& tag(e.tagName());
|
|
const QString& val(e.text());
|
|
|
|
if (tag == "lineWidth")
|
|
_width = Spatium(val.toDouble());
|
|
else if (tag == "lineLen")
|
|
_len = Spatium(val.toDouble());
|
|
else if (tag == "vertical")
|
|
vertical = val.toInt();
|
|
else
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// Compound
|
|
//---------------------------------------------------------
|
|
|
|
Compound::Compound(Score* s)
|
|
: Element(s)
|
|
{
|
|
}
|
|
|
|
Compound::Compound(const Compound& c)
|
|
: Element(c)
|
|
{
|
|
elemente.clear();
|
|
foreach(Element* e, c.elemente)
|
|
elemente.append(e->clone());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// draw
|
|
//---------------------------------------------------------
|
|
|
|
void Compound::draw(QPainter* painter) const
|
|
{
|
|
foreach(Element* e, elemente) {
|
|
QPointF pt(e->pos());
|
|
painter->translate(pt);
|
|
e->draw(painter);
|
|
painter->translate(-pt);
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// addElement
|
|
//---------------------------------------------------------
|
|
|
|
/**
|
|
offset \a x and \a y are in Point units
|
|
*/
|
|
|
|
void Compound::addElement(Element* e, qreal x, qreal y)
|
|
{
|
|
e->setPos(x, y);
|
|
e->setParent(this);
|
|
elemente.push_back(e);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// layout
|
|
//---------------------------------------------------------
|
|
|
|
void Compound::layout()
|
|
{
|
|
setbbox(QRectF());
|
|
for (iElement i = elemente.begin(); i != elemente.end(); ++i) {
|
|
Element* e = *i;
|
|
e->layout();
|
|
addbbox(e->bbox().translated(e->pos()));
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setSelected
|
|
//---------------------------------------------------------
|
|
|
|
void Compound::setSelected(bool f)
|
|
{
|
|
Element::setSelected(f);
|
|
for (ciElement i = elemente.begin(); i != elemente.end(); ++i)
|
|
(*i)->setSelected(f);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setVisible
|
|
//---------------------------------------------------------
|
|
|
|
void Compound::setVisible(bool f)
|
|
{
|
|
Element::setVisible(f);
|
|
for (ciElement i = elemente.begin(); i != elemente.end(); ++i)
|
|
(*i)->setVisible(f);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// clear
|
|
//---------------------------------------------------------
|
|
|
|
void Compound::clear()
|
|
{
|
|
foreach(Element* e, elemente) {
|
|
if (e->selected())
|
|
score()->deselect(e);
|
|
delete e;
|
|
}
|
|
elemente.clear();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// dump
|
|
//---------------------------------------------------------
|
|
|
|
void Element::dump() const
|
|
{
|
|
qDebug("---Element: %s, pos(%4.2f,%4.2f)\n"
|
|
" bbox(%g,%g,%g,%g)\n"
|
|
" abox(%g,%g,%g,%g)\n"
|
|
" parent: %p\n",
|
|
name(), ipos().x(), ipos().y(),
|
|
_bbox.x(), _bbox.y(), _bbox.width(), _bbox.height(),
|
|
abbox().x(), abbox().y(), abbox().width(), abbox().height(),
|
|
parent());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// RubberBand::draw
|
|
//---------------------------------------------------------
|
|
|
|
void RubberBand::draw(QPainter* painter) const
|
|
{
|
|
if (!showRubberBand)
|
|
return;
|
|
painter->setPen(Qt::red);
|
|
painter->drawLine(QLineF(_p1.x(), _p1.y(), _p2.x(), _p2.y()));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// mimeData
|
|
//---------------------------------------------------------
|
|
|
|
QByteArray Element::mimeData(const QPointF& dragOffset) const
|
|
{
|
|
QBuffer buffer;
|
|
buffer.open(QIODevice::WriteOnly);
|
|
Xml xml(&buffer);
|
|
xml.clipboardmode = true;
|
|
xml.stag("Element");
|
|
if (type() == NOTE)
|
|
xml.fTag("duration", static_cast<const Note*>(this)->chord()->duration());
|
|
if (!dragOffset.isNull())
|
|
xml.tag("dragOffset", dragOffset);
|
|
write(xml);
|
|
xml.etag();
|
|
buffer.close();
|
|
return buffer.buffer();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// readType
|
|
// return new position of QDomElement in e
|
|
//---------------------------------------------------------
|
|
|
|
ElementType Element::readType(QDomElement& e, QPointF* dragOffset, Fraction* duration)
|
|
{
|
|
ElementType type = INVALID;
|
|
|
|
for (e = e.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) {
|
|
if (e.tagName() == "dragOffset")
|
|
*dragOffset = readPoint(e);
|
|
else if (e.tagName() == "duration")
|
|
*duration = readFraction(e);
|
|
else if ((type = name2type(e.tagName())) == INVALID) {
|
|
domError(e);
|
|
break;
|
|
}
|
|
if (type != INVALID)
|
|
break;
|
|
}
|
|
return type;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// editDrag
|
|
//---------------------------------------------------------
|
|
|
|
void Element::editDrag(const EditData& ed)
|
|
{
|
|
score()->addRefresh(abbox());
|
|
setUserOff(userOff() + ed.delta);
|
|
score()->addRefresh(abbox());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// edit
|
|
// return true if event is accepted
|
|
//---------------------------------------------------------
|
|
|
|
bool Element::edit(MuseScoreView*, int, int key, Qt::KeyboardModifiers, const QString&)
|
|
{
|
|
if (key == Qt::Key_Home) {
|
|
setUserOff(QPoint());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// add
|
|
//---------------------------------------------------------
|
|
|
|
void Element::add(Element* e)
|
|
{
|
|
qDebug("Element: cannot add %s to %s\n", e->name(), name());
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// remove
|
|
//---------------------------------------------------------
|
|
|
|
void Element::remove(Element* e)
|
|
{
|
|
qDebug("Element: cannot remove %s from %s\n", e->name(), name());
|
|
abort();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// create
|
|
// Element factory
|
|
//---------------------------------------------------------
|
|
|
|
Element* Element::create(ElementType type, Score* score)
|
|
{
|
|
switch(type) {
|
|
case VOLTA: return new Volta(score);
|
|
case OTTAVA: return new Ottava(score);
|
|
case TEXTLINE: return new TextLine(score);
|
|
case TRILL: return new Trill(score);
|
|
case PEDAL: return new Pedal(score);
|
|
case HAIRPIN: return new Hairpin(score);
|
|
case CLEF: return new Clef(score);
|
|
case KEYSIG: return new KeySig(score);
|
|
case TIMESIG: return new TimeSig(score);
|
|
case BAR_LINE: return new BarLine(score);
|
|
case ARPEGGIO: return new Arpeggio(score);
|
|
case BREATH: return new Breath(score);
|
|
case GLISSANDO: return new Glissando(score);
|
|
case BRACKET: return new Bracket(score);
|
|
case ARTICULATION: return new Articulation(score);
|
|
case CHORDLINE: return new ChordLine(score);
|
|
case ACCIDENTAL: return new Accidental(score);
|
|
case DYNAMIC: return new Dynamic(score);
|
|
case TEXT: return new Text(score);
|
|
case INSTRUMENT_NAME: return new InstrumentName(score);
|
|
case STAFF_TEXT: return new StaffText(score);
|
|
case REHEARSAL_MARK: return new RehearsalMark(score);
|
|
case INSTRUMENT_CHANGE: return new InstrumentChange(score);
|
|
case NOTEHEAD: return new NoteHead(score);
|
|
case NOTEDOT: return new NoteDot(score);
|
|
case TREMOLO: return new Tremolo(score);
|
|
case LAYOUT_BREAK: return new LayoutBreak(score);
|
|
case MARKER: return new Marker(score);
|
|
case JUMP: return new Jump(score);
|
|
case REPEAT_MEASURE: return new RepeatMeasure(score);
|
|
case ICON: return new Icon(score);
|
|
case NOTE: return new Note(score);
|
|
case SYMBOL: return new Symbol(score);
|
|
case FSYMBOL: return new FSymbol(score);
|
|
case CHORD: return new Chord(score);
|
|
case REST: return new Rest(score);
|
|
case SPACER: return new Spacer(score);
|
|
case STAFF_STATE: return new StaffState(score);
|
|
case TEMPO_TEXT: return new TempoText(score);
|
|
case HARMONY: return new Harmony(score);
|
|
case FRET_DIAGRAM: return new FretDiagram(score);
|
|
case BEND: return new Bend(score);
|
|
case TREMOLOBAR: return new TremoloBar(score);
|
|
case LYRICS: return new Lyrics(score);
|
|
case FIGURED_BASS: return new FiguredBass(score);
|
|
case STEM: return new Stem(score);
|
|
case SLUR: return new Slur(score);
|
|
case ACCIDENTAL_BRACKET: return new AccidentalBracket(score);
|
|
case FINGERING: return new Fingering(score);
|
|
case HBOX: return new HBox(score);
|
|
case VBOX: return new VBox(score);
|
|
case TBOX: return new TBox(score);
|
|
case FBOX: return new FBox(score);
|
|
case MEASURE: return new Measure(score);
|
|
case TAB_DURATION_SYMBOL: return new TabDurationSymbol(score);
|
|
case OSSIA: return new Ossia(score);
|
|
|
|
case TEXTLINE_SEGMENT: // return new TextLineSegment(score);
|
|
|
|
case SLUR_SEGMENT:
|
|
case STEM_SLASH:
|
|
case LINE:
|
|
case IMAGE:
|
|
case TIE:
|
|
case PAGE:
|
|
case BEAM:
|
|
case HOOK:
|
|
case TUPLET:
|
|
case HAIRPIN_SEGMENT:
|
|
case OTTAVA_SEGMENT:
|
|
case TRILL_SEGMENT:
|
|
case VOLTA_SEGMENT:
|
|
case LEDGER_LINE:
|
|
case STAFF_LINES:
|
|
case SELECTION:
|
|
case LASSO:
|
|
case SHADOW_NOTE:
|
|
case RUBBERBAND:
|
|
case SEGMENT:
|
|
case SYSTEM:
|
|
case COMPOUND:
|
|
case ELEMENT:
|
|
case ELEMENT_LIST:
|
|
case STAFF_LIST:
|
|
case MEASURE_LIST:
|
|
case LAYOUT:
|
|
case MAXTYPE:
|
|
case INVALID: break;
|
|
}
|
|
qDebug("cannot create type <%s>\n", Element::name(type));
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// name
|
|
//---------------------------------------------------------
|
|
|
|
const char* Element::name(ElementType type)
|
|
{
|
|
switch(type) {
|
|
case SYMBOL: return "Symbol";
|
|
case FSYMBOL: return "FSymbol";
|
|
case TEXT: return "Text";
|
|
case INSTRUMENT_NAME: return "InstrumentName";
|
|
case SLUR_SEGMENT: return "SlurSegment";
|
|
case BAR_LINE: return "BarLine";
|
|
case STEM_SLASH: return "StemSlash";
|
|
case LINE: return "Line";
|
|
case BRACKET: return "Bracket";
|
|
case ARPEGGIO: return "Arpeggio";
|
|
case ACCIDENTAL: return "Accidental";
|
|
case NOTE: return "Note";
|
|
case STEM: return "Stem";
|
|
case CLEF: return "Clef";
|
|
case KEYSIG: return "KeySig";
|
|
case TIMESIG: return "TimeSig";
|
|
case REST: return "Rest";
|
|
case BREATH: return "Breath";
|
|
case GLISSANDO: return "Glissando";
|
|
case REPEAT_MEASURE: return "RepeatMeasure";
|
|
case IMAGE: return "Image";
|
|
case TIE: return "Tie";
|
|
case ARTICULATION: return "Articulation";
|
|
case CHORDLINE: return "ChordLine";
|
|
case DYNAMIC: return "Dynamic";
|
|
case PAGE: return "Page";
|
|
case BEAM: return "Beam";
|
|
case HOOK: return "Hook";
|
|
case LYRICS: return "Lyrics";
|
|
case FIGURED_BASS: return "FiguredBass";
|
|
case MARKER: return "Marker";
|
|
case JUMP: return "Jump";
|
|
case FINGERING: return "Fingering";
|
|
case TUPLET: return "Tuplet";
|
|
case TEMPO_TEXT: return "Tempo";
|
|
case STAFF_TEXT: return "StaffText";
|
|
case REHEARSAL_MARK: return "RehearsalMark";
|
|
case INSTRUMENT_CHANGE: return "InstrumentChange";
|
|
case HARMONY: return "Harmony";
|
|
case FRET_DIAGRAM: return "FretDiagram";
|
|
case BEND: return "Bend";
|
|
case TREMOLOBAR: return "TremoloBar";
|
|
case VOLTA: return "Volta";
|
|
case HAIRPIN_SEGMENT: return "HairpinSegment";
|
|
case OTTAVA_SEGMENT: return "OttavaSegment";
|
|
case TRILL_SEGMENT: return "TrillSegment";
|
|
case TEXTLINE_SEGMENT: return "TextLineSegment";
|
|
case VOLTA_SEGMENT: return "VoltaSegment";
|
|
case LAYOUT_BREAK: return "LayoutBreak";
|
|
case SPACER: return "Spacer";
|
|
case STAFF_STATE: return "StaffState";
|
|
case LEDGER_LINE: return "LedgerLine";
|
|
case NOTEHEAD: return "NoteHead";
|
|
case NOTEDOT: return "NoteDot";
|
|
case TREMOLO: return "Tremolo";
|
|
case MEASURE: return "Measure";
|
|
case STAFF_LINES: return "StaffLines";
|
|
case SELECTION: return "Selection";
|
|
case LASSO: return "Lasso";
|
|
case SHADOW_NOTE: return "ShadowNote";
|
|
case RUBBERBAND: return "RubberBand";
|
|
case HAIRPIN: return "HairPin";
|
|
case OTTAVA: return "Ottava";
|
|
case PEDAL: return "Pedal";
|
|
case TRILL: return "Trill";
|
|
case TEXTLINE: return "TextLine";
|
|
case SEGMENT: return "Segment";
|
|
case SYSTEM: return "System";
|
|
case COMPOUND: return "Compound";
|
|
case CHORD: return "Chord";
|
|
case SLUR: return "Slur";
|
|
case ELEMENT: return "Element";
|
|
case ELEMENT_LIST: return "ElementList";
|
|
case STAFF_LIST: return "StaffList";
|
|
case MEASURE_LIST: return "MeasureList";
|
|
case LAYOUT: return "Layout";
|
|
case HBOX: return "HBox";
|
|
case VBOX: return "VBox";
|
|
case TBOX: return "TBox";
|
|
case FBOX: return "FBox";
|
|
case ICON: return "Icon";
|
|
case OSSIA: return "Ossia";
|
|
case ACCIDENTAL_BRACKET: return "AccidentalBracket";
|
|
case TAB_DURATION_SYMBOL: return "TabDurationSymbol";
|
|
case INVALID:
|
|
case MAXTYPE:
|
|
break;
|
|
}
|
|
return "??";
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// name2type
|
|
//---------------------------------------------------------
|
|
|
|
ElementType Element::name2type(const QString& s)
|
|
{
|
|
for (int i = 0; i < MAXTYPE; ++i) {
|
|
if (s == elementNames[i])
|
|
return ElementType(i);
|
|
}
|
|
qDebug("name2type: invalid type <%s>\n", qPrintable(s));
|
|
return INVALID;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// name2Element
|
|
//---------------------------------------------------------
|
|
|
|
Element* Element::name2Element(const QString& s, Score* sc)
|
|
{
|
|
ElementType type = Element::name2type(s);
|
|
if (type == INVALID)
|
|
return 0;
|
|
return Element::create(type, sc);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// elementLessThan
|
|
//---------------------------------------------------------
|
|
|
|
bool elementLessThan(const Element* const e1, const Element* const e2)
|
|
{
|
|
return e1->z() > e2->z();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// getGrip
|
|
//---------------------------------------------------------
|
|
|
|
QPointF Element::getGrip(int) const
|
|
{
|
|
qreal _spatium = score()->spatium();
|
|
return QPointF(userOff().x() / _spatium, userOff().y() / _spatium);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setGrip
|
|
//---------------------------------------------------------
|
|
|
|
void Element::setGrip(int, const QPointF& pt)
|
|
{
|
|
qreal _spatium = score()->spatium();
|
|
setUserOff(QPointF(pt.x() * _spatium, pt.y() * _spatium));
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// collectElements
|
|
//---------------------------------------------------------
|
|
|
|
void collectElements(void* data, Element* e)
|
|
{
|
|
QList<Element*>* el = static_cast<QList<Element*>*>(data);
|
|
el->append(e);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// Space::operator+=
|
|
//---------------------------------------------------------
|
|
|
|
Space& Space::operator+=(const Space& s)
|
|
{
|
|
_lw += s._lw;
|
|
_rw += s._rw;
|
|
return *this;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// property
|
|
//---------------------------------------------------------
|
|
|
|
Property<Element>* Element::property(P_ID id) const
|
|
{
|
|
for (int i = 0;; ++i) {
|
|
if (propertyList[i].id == P_END)
|
|
break;
|
|
if (propertyList[i].id == id)
|
|
return &propertyList[i];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// getProperty
|
|
//---------------------------------------------------------
|
|
|
|
QVariant Element::getProperty(P_ID propertyId) const
|
|
{
|
|
Property<Element>* p = property(propertyId);
|
|
if (p)
|
|
return getVariant(propertyId, ((*(Element*)this).*(p->data))());
|
|
return QVariant();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setProperty
|
|
//---------------------------------------------------------
|
|
|
|
bool Element::setProperty(P_ID propertyId, const QVariant& v)
|
|
{
|
|
Property<Element>* p = property(propertyId);
|
|
if (p) {
|
|
setVariant(propertyId, ((*this).*(p->data))(), v);
|
|
setGenerated(false);
|
|
score()->addRefresh(canvasBoundingRect());
|
|
return true;
|
|
}
|
|
qDebug("Element::setProperty: unknown id %d, data <%s>", propertyId, qPrintable(v.toString()));
|
|
abort();
|
|
return false;
|
|
}
|
|
|
|
bool Element::setProperty(const QString& name, const QDomElement& e)
|
|
{
|
|
for (int i = 0;; ++i) {
|
|
P_ID id = propertyList[i].id;
|
|
if (id == P_END)
|
|
break;
|
|
if (propertyName(id) == name) {
|
|
QVariant v = ::getProperty(id, e);
|
|
setVariant(id, ((*this).*(propertyList[i].data))(), v);
|
|
setGenerated(false);
|
|
score()->addRefresh(canvasBoundingRect());
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// setVariant
|
|
//---------------------------------------------------------
|
|
|
|
void Element::setVariant(P_ID id, void* data, const QVariant& value)
|
|
{
|
|
if (id == P_VISIBLE) {
|
|
setVisible(value.toBool());
|
|
return;
|
|
}
|
|
switch(propertyType(id)) {
|
|
case T_BOOL:
|
|
*(bool*)data = value.toBool();
|
|
break;
|
|
case T_SUBTYPE:
|
|
case T_INT:
|
|
*(int*)data = value.toInt();
|
|
break;
|
|
case T_SREAL:
|
|
*(qreal*)data = value.toDouble() * spatium();
|
|
break;
|
|
case T_REAL:
|
|
*(qreal*)data = value.toDouble();
|
|
break;
|
|
case T_FRACTION:
|
|
*(Fraction*)data = value.value<Fraction>();
|
|
break;
|
|
case T_SCALE:
|
|
case T_POINT:
|
|
*(QPointF*)data = value.toPointF();
|
|
break;
|
|
case T_SIZE:
|
|
*(QSizeF*)data = value.toSizeF();
|
|
break;
|
|
case T_COLOR:
|
|
*(QColor*)data = value.value<QColor>();
|
|
break;
|
|
case T_DIRECTION:
|
|
case T_DIRECTION_H:
|
|
case T_LAYOUT_BREAK:
|
|
case T_VALUE_TYPE:
|
|
case T_BEAM_MODE:
|
|
*(int*)data = value.toInt();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// getVariant
|
|
// Return QVariant from void* to property.
|
|
// The external representation of the property is
|
|
// returned, suitable for writing to xml.
|
|
//---------------------------------------------------------
|
|
|
|
QVariant Element::getVariant(P_ID id, void* data) const
|
|
{
|
|
if (data) {
|
|
switch(propertyType(id)) {
|
|
case T_BOOL:
|
|
return QVariant(*(bool*)data);
|
|
case T_SUBTYPE:
|
|
case T_INT:
|
|
case T_DIRECTION:
|
|
case T_DIRECTION_H:
|
|
case T_LAYOUT_BREAK:
|
|
case T_VALUE_TYPE:
|
|
case T_BEAM_MODE:
|
|
return QVariant(*(int*)data);
|
|
case T_FRACTION:
|
|
return QVariant::fromValue(*(Fraction*)data);
|
|
case T_SREAL:
|
|
return QVariant((*(qreal*)data) / spatium());
|
|
case T_REAL:
|
|
return QVariant(*(qreal*)data);
|
|
case T_COLOR:
|
|
return QVariant(*(QColor*)data);
|
|
case T_POINT:
|
|
case T_SCALE:
|
|
return QVariant(*(QPointF*)data);
|
|
case T_SIZE:
|
|
return QVariant(*(QSizeF*)data);
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
|