From 35265cd3581232adc1f68b3a971752129d9252a0 Mon Sep 17 00:00:00 2001 From: ws Date: Tue, 16 Jan 2018 13:38:17 +0100 Subject: [PATCH] implement new fermata element --- libmscore/CMakeLists.txt | 2 +- libmscore/chordrest.cpp | 10 +- libmscore/cmd.cpp | 7 +- libmscore/edit.cpp | 6 +- libmscore/element.cpp | 6 +- libmscore/element.h | 15 +- libmscore/fermata.cpp | 391 ++++++++++++++++++ libmscore/fermata.h | 88 ++++ libmscore/hairpin.cpp | 2 +- libmscore/layout.cpp | 14 +- libmscore/lyrics.cpp | 2 +- libmscore/measure.cpp | 1 + libmscore/mscore.cpp | 1 - libmscore/note.cpp | 1 + libmscore/ottava.cpp | 14 +- libmscore/property.cpp | 4 +- libmscore/read114.cpp | 18 +- libmscore/read206.cpp | 121 +++++- libmscore/read206.h | 2 +- libmscore/rest.cpp | 2 +- libmscore/score.cpp | 4 +- libmscore/scoreElement.cpp | 1 + libmscore/scoreElement.h | 3 + libmscore/segment.cpp | 4 + libmscore/shape.cpp | 10 + libmscore/shape.h | 2 +- libmscore/stafftext.cpp | 4 +- libmscore/style.cpp | 24 +- libmscore/tempotext.cpp | 4 +- libmscore/trill.cpp | 4 +- libmscore/types.h | 10 + libmscore/vibrato.cpp | 4 +- libmscore/xmlwriter.cpp | 6 +- mscore/dragdrop.cpp | 7 +- mscore/editlyrics.cpp | 12 +- mscore/editstyle.cpp | 4 +- mscore/exportxml.cpp | 2 +- mscore/importmxmlpass2.cpp | 8 +- mscore/importmxmlpass2.h | 2 +- mscore/menus.cpp | 20 +- mscore/palette.cpp | 6 +- mscore/scoreview.cpp | 41 +- mscore/scoreview.h | 1 - .../compat206/articulations-ref.mscx | 104 +++-- mtest/libmscore/dynamic/tst_dynamic.cpp | 16 +- mtest/scripting/p1.log.ref | 4 +- 46 files changed, 785 insertions(+), 229 deletions(-) create mode 100644 libmscore/fermata.cpp create mode 100644 libmscore/fermata.h diff --git a/libmscore/CMakeLists.txt b/libmscore/CMakeLists.txt index f9461a1b151b9..b6b92f8220123 100644 --- a/libmscore/CMakeLists.txt +++ b/libmscore/CMakeLists.txt @@ -36,7 +36,7 @@ add_library ( ${LIB_SCRIPT_FILES} types.h segmentlist.cpp fingering.cpp accidental.cpp arpeggio.cpp - articulation.cpp barline.cpp beam.cpp bend.cpp box.cpp + fermata.cpp articulation.cpp barline.cpp beam.cpp bend.cpp box.cpp bracket.cpp breath.cpp bsp.cpp chord.cpp chordline.cpp chordlist.cpp chordrest.cpp clef.cpp cleflist.cpp drumset.cpp durationtype.cpp dynamic.cpp edit.cpp noteentry.cpp diff --git a/libmscore/chordrest.cpp b/libmscore/chordrest.cpp index d653029fb6071..e4f559cec3d88 100644 --- a/libmscore/chordrest.cpp +++ b/libmscore/chordrest.cpp @@ -452,7 +452,6 @@ void ChordRest::layoutArticulations() if (parent() == 0 || _articulations.empty()) return; qreal _spatium = spatium(); -// bool scale = !staff()->isDrumStaff(tick()); qreal pld = staff()->lineDistance(tick()); qreal _spStaff = _spatium * pld; // scaled to staff line distance for vert. pos. within a staff @@ -765,6 +764,7 @@ Element* ChordRest::drop(EditData& data) case ElementType::FRET_DIAGRAM: case ElementType::TREMOLOBAR: case ElementType::SYMBOL: + case ElementType::FERMATA: e->setTrack(track()); e->setParent(segment()); score()->undoAddElement(e); @@ -1492,11 +1492,11 @@ int ChordRest::lastVerse(Placement p) const void ChordRest::flipLyrics(Lyrics* l) { - Element::Placement p = l->placement(); - if (p == Element::Placement::ABOVE) - p = Element::Placement::BELOW; + Placement p = l->placement(); + if (p == Placement::ABOVE) + p = Placement::BELOW; else - p = Element::Placement::ABOVE; + p = Placement::ABOVE; int verses = lastVerse(p); l->undoChangeProperty(P_ID::VERSE, verses + 1); l->undoChangeProperty(P_ID::AUTOPLACE, true); diff --git a/libmscore/cmd.cpp b/libmscore/cmd.cpp index 816047cdf5610..42765feb59d36 100644 --- a/libmscore/cmd.cpp +++ b/libmscore/cmd.cpp @@ -17,6 +17,7 @@ #include +#include "types.h" #include "musescoreCore.h" #include "score.h" #include "utils.h" @@ -2318,9 +2319,9 @@ void Score::cmdMoveRest(Rest* rest, Direction dir) void Score::cmdMoveLyrics(Lyrics* lyrics, Direction dir) { - ChordRest* cr = lyrics->chordRest(); - int verse = lyrics->no(); - Element::Placement placement = lyrics->placement(); + ChordRest* cr = lyrics->chordRest(); + int verse = lyrics->no(); + Placement placement = lyrics->placement(); int newVerse; if (lyrics->placeAbove()) dir = (dir == Direction::UP) ? Direction::DOWN : Direction::UP; diff --git a/libmscore/edit.cpp b/libmscore/edit.cpp index d42e043efc0eb..d00bb9291f504 100644 --- a/libmscore/edit.cpp +++ b/libmscore/edit.cpp @@ -54,6 +54,7 @@ #include "excerpt.h" #include "breath.h" #include "glissando.h" +#include "fermata.h" namespace Ms { @@ -1294,10 +1295,11 @@ void Score::cmdFlip() || e->isOttavaSegment() || e->isTextLineSegment() || e->isPedalSegment() + || e->isFermata() || e->isTrillSegment()) { // getProperty() delegates call from spannerSegment to Spanner: - Element::Placement p = Element::Placement(e->getProperty(P_ID::PLACEMENT).toInt()); - p = (p == Element::Placement::ABOVE) ? Element::Placement::BELOW : Element::Placement::ABOVE; + Placement p = Placement(e->getProperty(P_ID::PLACEMENT).toInt()); + p = (p == Placement::ABOVE) ? Placement::BELOW : Placement::ABOVE; e->undoChangeProperty(P_ID::AUTOPLACE, true); e->undoChangeProperty(P_ID::PLACEMENT, int(p)); } diff --git a/libmscore/element.cpp b/libmscore/element.cpp index 4dadf99529d68..c92d6208e1cfd 100644 --- a/libmscore/element.cpp +++ b/libmscore/element.cpp @@ -90,6 +90,7 @@ #include "letring.h" #include "vibrato.h" #include "palmmute.h" +#include "fermata.h" namespace Ms { @@ -848,6 +849,7 @@ Element* Element::create(ElementType type, Score* score) case ElementType::GLISSANDO: return new Glissando(score); case ElementType::BRACKET: return new Bracket(score); case ElementType::ARTICULATION: return new Articulation(score); + case ElementType::FERMATA: return new Fermata(score); case ElementType::CHORDLINE: return new ChordLine(score); case ElementType::ACCIDENTAL: return new Accidental(score); case ElementType::DYNAMIC: return new Dynamic(score); @@ -1000,7 +1002,7 @@ QVariant Element::getProperty(P_ID propertyId) const case P_ID::USER_OFF: return _userOff; case P_ID::PLACEMENT: - return int(_placement); + return int(placement()); case P_ID::AUTOPLACE: return autoplace(); case P_ID::Z: @@ -1039,7 +1041,7 @@ bool Element::setProperty(P_ID propertyId, const QVariant& v) _userOff = v.toPointF(); break; case P_ID::PLACEMENT: - _placement = Placement(v.toInt()); + setPlacement(Placement(v.toInt())); break; case P_ID::AUTOPLACE: setAutoplace(v.toBool()); diff --git a/libmscore/element.h b/libmscore/element.h index 12116904fea5e..ea687d4220c64 100644 --- a/libmscore/element.h +++ b/libmscore/element.h @@ -143,16 +143,6 @@ class Element : public ScoreElement { | ElementFlag::VISIBLE }; // used for segments - protected: - mutable int _z; - QColor _color; ///< element color attribute - - public: - enum class Placement : char { - ABOVE, BELOW - }; - - private: Placement _placement; int _track; ///< staffIdx * VOICES + voice qreal _mag; ///< standard magnification (derived value) @@ -163,6 +153,10 @@ class Element : public ScoreElement { ///< valid after call to layout() uint _tag; ///< tag bitmask + protected: + mutable int _z; + QColor _color; ///< element color attribute + public: Element(Score* s = 0); Element(const Element&); @@ -521,7 +515,6 @@ extern void collectElements(void* data, Element* e); } // namespace Ms Q_DECLARE_METATYPE(Ms::ElementType); -Q_DECLARE_METATYPE(Ms::Element::Placement); #endif diff --git a/libmscore/fermata.cpp b/libmscore/fermata.cpp new file mode 100644 index 0000000000000..d8eb44cc0b83e --- /dev/null +++ b/libmscore/fermata.cpp @@ -0,0 +1,391 @@ +//============================================================================= +// MuseScore +// Music Composition & Notation +// +// Copyright (C) 2018 Werner Schweer +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 +// as published by the Free Software Foundation and appearing in +// the file LICENCE.GPL +//============================================================================= + +#include "fermata.h" +#include "score.h" +#include "chordrest.h" +#include "system.h" +#include "measure.h" +#include "staff.h" +#include "stafftype.h" +#include "undo.h" +#include "page.h" +#include "barline.h" +#include "sym.h" +#include "xml.h" + +namespace Ms { + +//--------------------------------------------------------- +// Fermata +//--------------------------------------------------------- + +Fermata::Fermata(Score* s) + : Element(s) + { + setFlags(ElementFlag::MOVABLE | ElementFlag::SELECTABLE); + setPlacement(Placement::ABOVE); + + _symId = SymId::noSym; + _timeStretch = 1.0; + setPlay(true); + } + +Fermata::Fermata(SymId id, Score* s) + : Fermata(s) + { + setSymId(id); + } + +//--------------------------------------------------------- +// read +//--------------------------------------------------------- + +void Fermata::read(XmlReader& e) + { + while (e.readNextStartElement()) { + if (!readProperties(e)) + e.unknown(); + } + } + +//--------------------------------------------------------- +// readProperties +//--------------------------------------------------------- + +bool Fermata::readProperties(XmlReader& e) + { + const QStringRef& tag(e.name()); + + printf("<<%s>>\n", qPrintable(tag.toString())); + + if (tag == "subtype") { + QString s = e.readElementText(); + SymId id = Sym::name2id(s); + setSymId(id); + } + else if ( tag == "play") + setPlay(e.readBool()); + else if (tag == "timeStretch") + _timeStretch = e.readDouble(); + else if (tag == "offset") { + if (score()->mscVersion() > 114) + Element::readProperties(e); + else + e.skipCurrentElement(); // ignore manual layout in older scores + } + else if (Element::readProperties(e)) + ; + else + return false; + return true; + } + +//--------------------------------------------------------- +// write +//--------------------------------------------------------- + +void Fermata::write(XmlWriter& xml) const + { + if (!xml.canWrite(this)) { + qDebug("%s not written", name()); + return; + } + xml.stag("Fermata"); + xml.tag("subtype", Sym::id2name(_symId)); + writeProperty(xml, P_ID::TIME_STRETCH); + writeProperty(xml, P_ID::PLAY); + Element::writeProperties(xml); + xml.etag(); + } + +//--------------------------------------------------------- +// userName +//--------------------------------------------------------- + +QString Fermata::userName() const + { + return Sym::id2userName(symId()); + } + +//--------------------------------------------------------- +// Symbol::draw +//--------------------------------------------------------- + +void Fermata::draw(QPainter* painter) const + { +#if 0 + SymId sym = symId(); + FermataShowIn flags = articulationList[int(articulationType())].flags; + if (staff()) { + if (staff()->staffGroup() == StaffGroup::TAB) { + if (!(flags & FermataShowIn::TABLATURE)) + return; + } + else { + if (!(flags & FermataShowIn::PITCHED_STAFF)) + return; + } + } +#endif + painter->setPen(curColor()); + drawSymbol(_symId, painter, QPointF(-0.5 * width(), 0.0)); + } + +//--------------------------------------------------------- +// chordRest +//--------------------------------------------------------- + +ChordRest* Fermata::chordRest() const + { + if (parent() && parent()->isChordRest()) + return toChordRest(parent()); + return 0; + } + +//--------------------------------------------------------- +// measure +//--------------------------------------------------------- + +Measure* Fermata::measure() const + { + Segment* s = segment(); + return toMeasure(s ? s->parent() : 0); + } + +//--------------------------------------------------------- +// system +//--------------------------------------------------------- + +System* Fermata::system() const + { + Measure* m = measure(); + return toSystem(m ? m->parent() : 0); + } + +//--------------------------------------------------------- +// page +//--------------------------------------------------------- + +Page* Fermata::page() const + { + System* s = system(); + return toPage(s ? s->parent() : 0); + } + +//--------------------------------------------------------- +// layout +// height() and width() should return sensible +// values when calling this method +//--------------------------------------------------------- + +void Fermata::layout() + { + QRectF b(symBbox(_symId)); + setbbox(b.translated(-0.5 * b.width(), 0.0)); + + Segment* s = segment(); + if (!s) { // for use in palette + setPos(QPointF()); // for palette + return; + } + + qreal _spatium = spatium(); + qreal dist = _spatium * 2; + qreal noteHeadWidth = score()->noteHeadWidth() * staff()->mag(0); + qreal x = noteHeadWidth * .5; + qreal y; + + if (placeAbove()) + y = -dist; + else + y = dist + staff()->height(); + setPos(QPointF(x, y)); + + if (!autoplace()) { + adjustReadPos(); + return; + } + setUserOff(QPointF()); + + // check for collisions + + qreal minDistance = _spatium * .5; // score()->styleP(StyleIdx::dynamicsMinDistance); + const Shape& s1 = s->measure()->staffShape(staffIdx()); + Shape s2 = shape().translated(s->pos() + pos()); + + if (placeAbove()) { + qreal d = s2.minVerticalDistance(s1); + if (d > -minDistance) + rUserYoffset() = -d - minDistance; + } + else { + qreal d = s1.minVerticalDistance(s2); + if (d > -minDistance) + rUserYoffset() = d + minDistance; + } + } + +//--------------------------------------------------------- +// reset +//--------------------------------------------------------- + +void Fermata::reset() + { + Element::reset(); + } + +//--------------------------------------------------------- +// dragAnchor +//--------------------------------------------------------- + +QLineF Fermata::dragAnchor() const + { + return QLineF(canvasPos(), parent()->canvasPos()); + } + +//--------------------------------------------------------- +// getProperty +//--------------------------------------------------------- + +QVariant Fermata::getProperty(P_ID propertyId) const + { + switch (propertyId) { + case P_ID::TIME_STRETCH: + return timeStretch(); + case P_ID::PLAY: + return play(); + default: + return Element::getProperty(propertyId); + } + } + +//--------------------------------------------------------- +// setProperty +//--------------------------------------------------------- + +bool Fermata::setProperty(P_ID propertyId, const QVariant& v) + { + switch (propertyId) { + case P_ID::PLACEMENT: { + Placement p = Placement(v.toInt()); + if (p != placement()) { + QString s = Sym::id2name(_symId); + bool up = placeAbove(); + if (s.endsWith(up ? "Above" : "Below")) { + QString s2 = s.left(s.size() - 5) + (up ? "Below" : "Above"); + _symId = Sym::name2id(s2); + } + setPlacement(p); + } + } + break; + case P_ID::PLAY: + setPlay(v.toBool()); + break; + case P_ID::TIME_STRETCH: + setTimeStretch(v.toDouble()); + score()->fixTicks(); + break; + default: + return Element::setProperty(propertyId, v); + } + triggerLayout(); + return true; + } + +//--------------------------------------------------------- +// propertyDefault +//--------------------------------------------------------- + +QVariant Fermata::propertyDefault(P_ID propertyId) const + { + switch (propertyId) { + case P_ID::PLACEMENT: + return int(Placement::ABOVE); + case P_ID::TIME_STRETCH: + return 1.0; // articulationList[int(articulationType())].timeStretch; + case P_ID::PLAY: + return true; + default: + break; + } + return Element::propertyDefault(propertyId); + } + +//--------------------------------------------------------- +// propertyStyle +//--------------------------------------------------------- + +PropertyFlags& Fermata::propertyFlags(P_ID id) + { +#if 0 + switch (id) { + case P_ID::TIME_STRETCH: + return PropertyFlags::NOSTYLE; + + default: + break; + } +#endif + return Element::propertyFlags(id); + } + +//--------------------------------------------------------- +// getPropertyStyle +//--------------------------------------------------------- + +StyleIdx Fermata::getPropertyStyle(P_ID id) const + { + switch (id) { + default: + break; + } + return StyleIdx::NOSTYLE; + } + +//--------------------------------------------------------- +// resetProperty +//--------------------------------------------------------- + +void Fermata::resetProperty(P_ID id) + { + switch (id) { + case P_ID::TIME_STRETCH: + setProperty(id, propertyDefault(id)); + return; + + default: + break; + } + Element::resetProperty(id); + } + +//--------------------------------------------------------- +// mag +//--------------------------------------------------------- + +qreal Fermata::mag() const + { + return parent() ? parent()->mag() * score()->styleD(StyleIdx::articulationMag): 1.0; + } + +//--------------------------------------------------------- +// accessibleInfo +//--------------------------------------------------------- + +QString Fermata::accessibleInfo() const + { + return QString("%1: %2").arg(Element::accessibleInfo()).arg(userName()); + } + +} diff --git a/libmscore/fermata.h b/libmscore/fermata.h new file mode 100644 index 0000000000000..602e3cc544fc7 --- /dev/null +++ b/libmscore/fermata.h @@ -0,0 +1,88 @@ +//============================================================================= +// MuseScore +// Music Composition & Notation +// +// Copyright (C) 2018 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 __FERMATA_H__ +#define __FERMATA_H__ + +#include "element.h" +#include "mscore.h" + +namespace Ms { + +class ChordRest; +class Segment; +class Measure; +class System; +class Page; + +enum class SymId; + +//--------------------------------------------------------- +// Fermata +//--------------------------------------------------------- + +class Fermata final : public Element { + SymId _symId; + qreal _timeStretch; + bool _play; + + virtual void draw(QPainter*) const override; + + public: + Fermata(Score*); + Fermata(SymId, Score*); + Fermata &operator=(const Fermata&) = delete; + + virtual Fermata* clone() const override { return new Fermata(*this); } + virtual ElementType type() const override { return ElementType::FERMATA; } + + virtual qreal mag() const override; + + SymId symId() const { return _symId; } + void setSymId(SymId id) { _symId = id; } + virtual int subtype() const override { return int(_symId); } + QString userName() const; + + virtual void layout() override; + + virtual void read(XmlReader&) override; + virtual void write(XmlWriter& xml) const override; + virtual bool readProperties(XmlReader&) override; + + virtual void reset() override; + virtual QLineF dragAnchor() const override; + + virtual QVariant getProperty(P_ID propertyId) const override; + virtual bool setProperty(P_ID propertyId, const QVariant&) override; + virtual QVariant propertyDefault(P_ID) const override; + virtual PropertyFlags& propertyFlags(P_ID) override; + virtual void resetProperty(P_ID id) override; + StyleIdx getPropertyStyle(P_ID id) const override; + + ChordRest* chordRest() const; + Segment* segment() const { return toSegment(parent()); } + Measure* measure() const; + System* system() const; + Page* page() const; + + qreal timeStretch() const { return _timeStretch; } + void setTimeStretch(qreal val) { _timeStretch = val; } + + bool play() const { return _play; } + void setPlay(bool val) { _play = val; } + + QString accessibleInfo() const override; + }; + +} // namespace Ms +#endif + diff --git a/libmscore/hairpin.cpp b/libmscore/hairpin.cpp index 6ac6036a99310..6f184a98bbc24 100644 --- a/libmscore/hairpin.cpp +++ b/libmscore/hairpin.cpp @@ -772,7 +772,7 @@ QVariant Hairpin::propertyDefault(P_ID id) const return int(Qt::SolidLine); return int(Qt::CustomDashLine); case P_ID::PLACEMENT: - return int(Element::Placement::BELOW); + return int(Placement::BELOW); case P_ID::BEGIN_FONT_FACE: case P_ID::BEGIN_FONT_SIZE: diff --git a/libmscore/layout.cpp b/libmscore/layout.cpp index efc148e3428e8..fcd433c28a8db 100644 --- a/libmscore/layout.cpp +++ b/libmscore/layout.cpp @@ -2472,7 +2472,13 @@ void Score::getNextMeasure(LayoutContext& lc) } else if (isMaster() && segment.isChordRestType()) { for (Element* e : segment.annotations()) { - if (!(e->isTempoText() || e->isDynamic() || e->isRehearsalMark() || e->isFretDiagram() || e->isStaffText() || e->isFiguredBass())) + if (!(e->isTempoText() + || e->isDynamic() + || e->isFermata() + || e->isRehearsalMark() + || e->isFretDiagram() + || e->isStaffText() + || e->isFiguredBass())) e->layout(); } // TODO, this is not going to work, we just cleaned the tempomap @@ -3324,6 +3330,12 @@ System* Score::collectSystem(LayoutContext& lc) m->staffShape(si).add(tt->shape().translated(s->pos() + e->pos())); } } + else if (e->isFermata()) { + e->layout(); + int si = e->staffIdx(); + s->staffShape(si).add(e->shape().translated(e->pos())); + m->staffShape(si).add(e->shape().translated(s->pos() + e->pos())); + } } } } diff --git a/libmscore/lyrics.cpp b/libmscore/lyrics.cpp index f6486cbe8fc37..e63de20fcd94c 100644 --- a/libmscore/lyrics.cpp +++ b/libmscore/lyrics.cpp @@ -30,7 +30,7 @@ static const qreal TWICE = 2.0; // searchNextLyrics //--------------------------------------------------------- -static Lyrics* searchNextLyrics(Segment* s, int staffIdx, int verse, Element::Placement p) +static Lyrics* searchNextLyrics(Segment* s, int staffIdx, int verse, Placement p) { Lyrics* l = 0; while ((s = s->next1(SegmentType::ChordRest))) { diff --git a/libmscore/measure.cpp b/libmscore/measure.cpp index e06eb78e32840..fb8294174fd91 100644 --- a/libmscore/measure.cpp +++ b/libmscore/measure.cpp @@ -2125,6 +2125,7 @@ void Measure::read(XmlReader& e, int staffIdx) || tag == "InstrumentChange" || tag == "StaffState" || tag == "FiguredBass" + || tag == "Fermata" ) { Element* el = Element::name2Element(tag, score()); // hack - needed because tick tags are unreliable in 1.3 scores diff --git a/libmscore/mscore.cpp b/libmscore/mscore.cpp index 909d96c1ef461..619c588586405 100644 --- a/libmscore/mscore.cpp +++ b/libmscore/mscore.cpp @@ -227,7 +227,6 @@ void MScore::init() qRegisterMetaType ("ValueType"); qRegisterMetaType("DirectionH"); - qRegisterMetaType("Placement"); qRegisterMetaType ("Anchor"); qRegisterMetaType ("NoteHeadGroup"); qRegisterMetaType("NoteHeadType"); diff --git a/libmscore/note.cpp b/libmscore/note.cpp index 6e936968755ac..50e39691731d0 100644 --- a/libmscore/note.cpp +++ b/libmscore/note.cpp @@ -1553,6 +1553,7 @@ bool Note::acceptDrop(EditData& data) const bool isTablature = staff()->isTabStaff(tick()); bool tabFingering = staff()->staffType(tick())->showTabFingering(); return (type == ElementType::ARTICULATION + || type == ElementType::FERMATA || type == ElementType::CHORDLINE || type == ElementType::TEXT || type == ElementType::REHEARSAL_MARK diff --git a/libmscore/ottava.cpp b/libmscore/ottava.cpp index 1e7675e848b10..14e58662155aa 100644 --- a/libmscore/ottava.cpp +++ b/libmscore/ottava.cpp @@ -33,7 +33,7 @@ struct OttavaDefault { SymId numbersOnlyId; QPointF offset; qreal hookDirection; - Element::Placement place; + Placement place; int shift; const char* name; const char* numbersOnlyName; @@ -41,12 +41,12 @@ struct OttavaDefault { // order is important, should be the same as OttavaType static const OttavaDefault ottavaDefault[] = { - { SymId::ottavaAlta, SymId::ottava, QPointF(0.0, .7), 1.0, Element::Placement::ABOVE, 12, "8va", "8" }, - { SymId::ottavaBassaBa, SymId::ottava, QPointF(0.0, -1.0), -1.0, Element::Placement::BELOW, -12, "8vb", "8" }, - { SymId::quindicesimaAlta, SymId::quindicesima, QPointF(0.0, .7), 1.0, Element::Placement::ABOVE, 24, "15ma", "15" }, - { SymId::quindicesimaBassa, SymId::quindicesima, QPointF(0.0, -1.0), -1.0, Element::Placement::BELOW, -24, "15mb", "15" }, - { SymId::ventiduesimaAlta, SymId::ventiduesima, QPointF(0.0, .7), 1.0, Element::Placement::ABOVE, 36, "22ma", "22" }, - { SymId::ventiduesimaBassa, SymId::ventiduesima, QPointF(0.0, -1.0), -1.0, Element::Placement::BELOW, -36, "22mb", "22" } + { SymId::ottavaAlta, SymId::ottava, QPointF(0.0, .7), 1.0, Placement::ABOVE, 12, "8va", "8" }, + { SymId::ottavaBassaBa, SymId::ottava, QPointF(0.0, -1.0), -1.0, Placement::BELOW, -12, "8vb", "8" }, + { SymId::quindicesimaAlta, SymId::quindicesima, QPointF(0.0, .7), 1.0, Placement::ABOVE, 24, "15ma", "15" }, + { SymId::quindicesimaBassa, SymId::quindicesima, QPointF(0.0, -1.0), -1.0, Placement::BELOW, -24, "15mb", "15" }, + { SymId::ventiduesimaAlta, SymId::ventiduesima, QPointF(0.0, .7), 1.0, Placement::ABOVE, 36, "22ma", "22" }, + { SymId::ventiduesimaBassa, SymId::ventiduesima, QPointF(0.0, -1.0), -1.0, Placement::BELOW, -36, "22mb", "22" } }; //--------------------------------------------------------- diff --git a/libmscore/property.cpp b/libmscore/property.cpp index 41f3cc2fab6fd..f3ae459f3e3d0 100644 --- a/libmscore/property.cpp +++ b/libmscore/property.cpp @@ -447,9 +447,9 @@ QVariant getProperty(P_ID id, XmlReader& e) case P_TYPE::PLACEMENT: { QString value(e.readElementText()); if (value == "above") - return QVariant(int(Element::Placement::ABOVE)); + return QVariant(int(Placement::ABOVE)); else if (value == "below") - return QVariant(int(Element::Placement::BELOW)); + return QVariant(int(Placement::BELOW)); } break; case P_TYPE::BARLINE_TYPE: { diff --git a/libmscore/read114.cpp b/libmscore/read114.cpp index c3c8eb78823de..2ad499716dc32 100644 --- a/libmscore/read114.cpp +++ b/libmscore/read114.cpp @@ -932,10 +932,11 @@ static void readChord(Chord* chord, XmlReader& e) chord->add(note); } else if (tag == "Attribute" || tag == "Articulation") { - Articulation* atr = new Articulation(chord->score()); - atr->setTrack(chord->track()); - readArticulation(atr, e); - chord->add(atr); + Element* el = readArticulation(chord, e); + if (el->isFermata()) + chord->segment()->add(el); + else + chord->add(el); } else if (chord->readProperties(e)) ; @@ -953,10 +954,11 @@ static void readRest(Rest* rest, XmlReader& e) while (e.readNextStartElement()) { const QStringRef& tag(e.name()); if (tag == "Attribute" || tag == "Articulation") { - Articulation* atr = new Articulation(rest->score()); - atr->setTrack(rest->track()); - readArticulation(atr, e); - rest->add(atr); + Element* el = readArticulation(rest, e); + if (el->isFermata()) + rest->segment()->add(el); + else + rest->add(el); } else if (rest->readProperties(e)) ; diff --git a/libmscore/read206.cpp b/libmscore/read206.cpp index 98ccd0480cf32..c8b401d376aed 100644 --- a/libmscore/read206.cpp +++ b/libmscore/read206.cpp @@ -49,6 +49,7 @@ #include "rehearsalmark.h" #include "box.h" #include "textframe.h" +#include "fermata.h" #ifdef OMR #include "omr/omr.h" @@ -995,10 +996,11 @@ static void readChord(Chord* chord, XmlReader& e) chord->add(note); } else if (tag == "Articulation") { - Articulation* atr = new Articulation(chord->score()); - atr->setTrack(chord->track()); - atr->read(e); - chord->add(atr); + Element* el = readArticulation(chord, e); + if (el->isFermata()) + chord->segment()->add(el); + else + chord->add(el); } else if (chord->readProperties(e)) ; @@ -1322,24 +1324,51 @@ SymId oldArticulationNames2SymId(const QString& s) return SymId::noSym; } +//--------------------------------------------------------- +// setFermataPlacement +// set fermata placement from old ArticulationAnchor +// for backwards compatibility +//--------------------------------------------------------- + +static void setFermataPlacement(Element* el, ArticulationAnchor anchor) + { + switch (anchor) { + case ArticulationAnchor::TOP_STAFF: + case ArticulationAnchor::TOP_CHORD: + el->setPlacement(Placement::ABOVE); + break; + + case ArticulationAnchor::BOTTOM_STAFF: + case ArticulationAnchor::BOTTOM_CHORD: + el->setPlacement(Placement::BELOW); + break; + default: + break; + } + } + //--------------------------------------------------------- // readArticulation //--------------------------------------------------------- -void readArticulation(Articulation* a, XmlReader& e) +Element* readArticulation(ChordRest* cr, XmlReader& e) { - a->setSymId(SymId::fermataAbove); // default -- backward compatibility (no type = ufermata in 1.2) + Element* el = 0; + SymId sym = SymId::fermataAbove; // default -- backward compatibility (no type = ufermata in 1.2) + ArticulationAnchor anchor = ArticulationAnchor::TOP_STAFF; + Direction direction = Direction::AUTO; + while (e.readNextStartElement()) { const QStringRef& tag(e.name()); if (tag == "subtype") { QString s = e.readElementText(); if (s[0].isDigit()) { int oldType = s.toInt(); - a->setSymId(articulationNames[oldType].id); + sym = articulationNames[oldType].id; } else { - a->setSymId(oldArticulationNames2SymId(s)); - if (a->symId() == SymId::noSym) { + sym = oldArticulationNames2SymId(s); + if (sym == SymId::noSym) { struct { const char* name; bool up; @@ -1374,22 +1403,68 @@ void readArticulation(Articulation* a, XmlReader& e) int n = sizeof(al) / sizeof(*al); for (i = 0; i < n; ++i) { if (s == al[i].name) { - a->setSymId(al[i].id); - a->setUp(al[i].up); - a->setDirection(a->up() ? Direction::UP : Direction::DOWN); + sym = al[i].id; + bool up = al[i].up; + direction = up ? Direction::UP : Direction::DOWN; break; } } - if (i == n) - qDebug("Articulation: unknown type <%s>", qPrintable(s)); + if (i == n) { + sym = Sym::name2id(s); + if (sym == SymId::noSym) + qDebug("Articulation: unknown type <%s>", qPrintable(s)); + } + } + } + switch (sym) { + case SymId::fermataAbove: + case SymId::fermataBelow: + case SymId::fermataShortAbove: + case SymId::fermataShortBelow: + case SymId::fermataLongAbove: + case SymId::fermataLongBelow: + case SymId::fermataVeryLongAbove: + case SymId::fermataVeryLongBelow: + el = new Fermata(sym, cr->score()); + setFermataPlacement(el, anchor); + break; + default: + el = new Articulation(sym, cr->score()); +// toArticulation(el)->setAnchor(anchor); + toArticulation(el)->setDirection(direction); + break; + }; + } + else if (tag == "anchor") { + if (!el) + anchor = ArticulationAnchor(e.readInt()); + else { + if (el->isFermata()) { + anchor = ArticulationAnchor(e.readInt()); + setFermataPlacement(el, anchor); } + else + el->readProperties(e); } } - else if (a->readProperties(e)) - ; - else - e.unknown(); + else if (tag == "direction") { + if (!el) + direction = toDirection(e.readElementText()); + else { + if (!el->isFermata()) + el->readProperties(e); + } + } + else { + if (!el) { + qDebug("not handled <%s>", qPrintable(tag.toString())); + } + if (!el->readProperties(e)) + e.unknown(); + } } + el->setTrack(cr->staffIdx() * VOICES); + return el; } //--------------------------------------------------------- @@ -1403,8 +1478,11 @@ static void readRest(Rest* rest, XmlReader& e) if (tag == "Articulation") { Articulation* atr = new Articulation(rest->score()); atr->setTrack(rest->track()); - readArticulation(atr, e); - rest->add(atr); + Element* el = readArticulation(rest, e); + if (el->isFermata()) + rest->segment()->add(el); + else + rest->add(el); } else if (rest->readProperties(e)) ; @@ -1514,8 +1592,9 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e) else if (tag == "Chord") { Chord* chord = new Chord(score); chord->setTrack(e.track()); - readChord(chord, e); segment = m->getSegment(SegmentType::ChordRest, e.tick()); + chord->setParent(segment); + readChord(chord, e); if (chord->noteType() != NoteType::NORMAL) graceNotes.push_back(chord); else { diff --git a/libmscore/read206.h b/libmscore/read206.h index e271fc63b18cf..f8e2875655f97 100644 --- a/libmscore/read206.h +++ b/libmscore/read206.h @@ -65,7 +65,7 @@ class PageFormat { qreal oddRightMargin() const { return _size.width() - _printableWidth - _oddLeftMargin; } }; -extern void readArticulation(Articulation*, XmlReader&); +extern Element* readArticulation(ChordRest*, XmlReader&); extern void setPageFormat(MStyle*, const PageFormat&); extern void initPageFormat(MStyle*, PageFormat*); extern void readTextStyle206(MStyle* style, XmlReader& e); diff --git a/libmscore/rest.cpp b/libmscore/rest.cpp index 669d317376a49..81ca17d42d651 100644 --- a/libmscore/rest.cpp +++ b/libmscore/rest.cpp @@ -185,7 +185,7 @@ bool Rest::acceptDrop(EditData& data) const || (type == ElementType::ICON && toIcon(e)->iconType() == IconType::BEAM32) || (type == ElementType::ICON && toIcon(e)->iconType() == IconType::BEAM64) || (type == ElementType::ICON && toIcon(e)->iconType() == IconType::AUTOBEAM) - || (type == ElementType::ARTICULATION && toArticulation(e)->isFermata()) + || (type == ElementType::FERMATA) || (type == ElementType::CLEF) || (type == ElementType::KEYSIG) || (type == ElementType::TIMESIG) diff --git a/libmscore/score.cpp b/libmscore/score.cpp index 67719aed08acb..a7b3ee5be8cfa 100644 --- a/libmscore/score.cpp +++ b/libmscore/score.cpp @@ -3837,7 +3837,7 @@ QString Score::extractLyrics() maxLyrics = cr->lyrics().size(); if (playCount >= int(cr->lyrics().size())) continue; - Lyrics* l = cr->lyrics(playCount, Element::Placement::BELOW); // TODO: ABOVE + Lyrics* l = cr->lyrics(playCount, Placement::BELOW); // TODO: ABOVE if (!l) continue; found = true; @@ -3866,7 +3866,7 @@ QString Score::extractLyrics() maxLyrics = cr->lyrics().size(); if (lyricsNumber >= cr->lyrics().size()) continue; - Lyrics* l = cr->lyrics(lyricsNumber, Element::Placement::BELOW); // TODO + Lyrics* l = cr->lyrics(lyricsNumber, Placement::BELOW); // TODO if (!l) continue; found = true; diff --git a/libmscore/scoreElement.cpp b/libmscore/scoreElement.cpp index 0db258874c972..45f0e5f01b7b8 100644 --- a/libmscore/scoreElement.cpp +++ b/libmscore/scoreElement.cpp @@ -51,6 +51,7 @@ static const ElementName elementNames[] = { { ElementType::REPEAT_MEASURE, "RepeatMeasure", QT_TRANSLATE_NOOP("elementName", "Repeat Measure") }, { ElementType::TIE, "Tie", QT_TRANSLATE_NOOP("elementName", "Tie") }, { ElementType::ARTICULATION, "Articulation", QT_TRANSLATE_NOOP("elementName", "Articulation") }, + { ElementType::FERMATA, "Fermata", QT_TRANSLATE_NOOP("elementName", "Fermata") }, { ElementType::CHORDLINE, "ChordLine", QT_TRANSLATE_NOOP("elementName", "Chord Line") }, { ElementType::DYNAMIC, "Dynamic", QT_TRANSLATE_NOOP("elementName", "Dynamic") }, { ElementType::BEAM, "Beam", QT_TRANSLATE_NOOP("elementName", "Beam") }, diff --git a/libmscore/scoreElement.h b/libmscore/scoreElement.h index 392dc318e83d0..6c5f8d78793df 100644 --- a/libmscore/scoreElement.h +++ b/libmscore/scoreElement.h @@ -119,6 +119,7 @@ class BagpipeEmbellishment; class LineSegment; class BSymbol; class TextLineBase; +class Fermata; class LetRing; class LetRingSegment; @@ -225,6 +226,7 @@ class ScoreElement { CONVERT(Chord, CHORD) CONVERT(BarLine, BAR_LINE) CONVERT(Articulation, ARTICULATION) + CONVERT(Fermata, FERMATA) CONVERT(Marker, MARKER) CONVERT(Clef, CLEF) CONVERT(KeySig, KEYSIG) @@ -441,6 +443,7 @@ static inline const a* to##a(const ScoreElement* e) { Q_ASSERT(e == 0 || e->is## CONVERT(Chord) CONVERT(BarLine) CONVERT(Articulation) + CONVERT(Fermata) CONVERT(Marker) CONVERT(Clef) CONVERT(KeySig) diff --git a/libmscore/segment.cpp b/libmscore/segment.cpp index 6adbe189b190c..633adb112c768 100644 --- a/libmscore/segment.cpp +++ b/libmscore/segment.cpp @@ -462,6 +462,7 @@ void Segment::add(Element* el) case ElementType::TREMOLOBAR: case ElementType::TAB_DURATION_SYMBOL: case ElementType::FIGURED_BASS: + case ElementType::FERMATA: _annotations.push_back(el); break; @@ -610,6 +611,7 @@ void Segment::remove(Element* el) case ElementType::TEMPO_TEXT: case ElementType::TEXT: case ElementType::TREMOLOBAR: + case ElementType::FERMATA: removeAnnotation(el); break; @@ -1830,6 +1832,8 @@ void Segment::createShape(int staffIdx) && !e->isSymbol() && !e->isFSymbol() && !e->isSystemText() + && !e->isArticulation() + && !e->isFermata() && !e->isStaffText()) s.add(e->shape().translated(e->pos())); } diff --git a/libmscore/shape.cpp b/libmscore/shape.cpp index 31806d8360084..805162d53a7ba 100644 --- a/libmscore/shape.cpp +++ b/libmscore/shape.cpp @@ -267,6 +267,16 @@ void ShapeElement::dump() const { printf(" %s: %f %f %f %f\n", text ? text : "", x(), y(), width(), height()); } + +//--------------------------------------------------------- +// add +//--------------------------------------------------------- + +void Shape::add(const QRectF& r, const char* t) + { + push_back(ShapeElement(r, t)); + } + #endif #ifdef DEBUG_SHAPES diff --git a/libmscore/shape.h b/libmscore/shape.h index 549305b19e00b..e66e24db11c12 100644 --- a/libmscore/shape.h +++ b/libmscore/shape.h @@ -51,7 +51,7 @@ class Shape : std::vector { void add(const Shape& s) { insert(end(), s.begin(), s.end()); } #ifndef NDEBUG - void add(const QRectF& r, const char* t = 0) { push_back(ShapeElement(r, t)); } + void add(const QRectF& r, const char* t = 0); #else void add(const QRectF& r) { push_back(r); } #endif diff --git a/libmscore/stafftext.cpp b/libmscore/stafftext.cpp index cd7a3d31e8fc9..bd0cf9bed712d 100644 --- a/libmscore/stafftext.cpp +++ b/libmscore/stafftext.cpp @@ -212,7 +212,7 @@ void StaffText::layout() // TODO: add above/below offset properties QPointF p(offset() * (offsetType() == OffsetType::SPATIUM ? spatium() : DPI)); - if (placement() == Element::Placement::BELOW) + if (placement() == Placement::BELOW) p.ry() = - p.ry() + lineHeight(); setPos(p); TextBase::layout1(); @@ -224,7 +224,7 @@ void StaffText::layout() Shape s1 = segment()->measure()->staffShape(staffIdx()); Shape s2 = shape().translated(segment()->pos() + pos()); - if (placement() == Element::Placement::ABOVE) { + if (placement() == Placement::ABOVE) { qreal d = s2.minVerticalDistance(s1); if (d > -minDistance) rUserYoffset() = -d - minDistance; diff --git a/libmscore/style.cpp b/libmscore/style.cpp index 594ca0a0d9f90..e0f8ce1de21d6 100644 --- a/libmscore/style.cpp +++ b/libmscore/style.cpp @@ -71,7 +71,7 @@ static const StyleType styleTypes[] { { StyleIdx::minSystemDistance, "minSystemDistance", Spatium(8.5) }, { StyleIdx::maxSystemDistance, "maxSystemDistance", Spatium(15.0) }, - { StyleIdx::lyricsPlacement, "lyricsPlacement", int(Element::Placement::BELOW) }, + { StyleIdx::lyricsPlacement, "lyricsPlacement", int(Placement::BELOW) }, { StyleIdx::lyricsPosAbove, "lyricsPosAbove", Spatium(-2.0) }, { StyleIdx::lyricsPosBelow, "lyricsPosBelow", Spatium(2.0) }, { StyleIdx::lyricsMinTopDistance, "lyricsMinTopDistance", Spatium(1.0) }, @@ -167,14 +167,14 @@ static const StyleType styleTypes[] { { StyleIdx::articulationMag, "articulationMag", QVariant(1.0) }, { StyleIdx::lastSystemFillLimit, "lastSystemFillLimit", QVariant(0.3) }, - { StyleIdx::hairpinPlacement, "hairpinPlacement", int(Element::Placement::BELOW) }, + { StyleIdx::hairpinPlacement, "hairpinPlacement", int(Placement::BELOW) }, { StyleIdx::hairpinPosAbove, "hairpinPosAbove", Spatium(-3.5) }, { StyleIdx::hairpinPosBelow, "hairpinPosBelow", Spatium(3.5) }, { StyleIdx::hairpinHeight, "hairpinHeight", Spatium(1.2) }, { StyleIdx::hairpinContHeight, "hairpinContHeight", Spatium(0.5) }, { StyleIdx::hairpinLineWidth, "hairpinWidth", Spatium(0.13) }, - { StyleIdx::pedalPlacement, "pedalPlacement", int(Element::Placement::BELOW) }, + { StyleIdx::pedalPlacement, "pedalPlacement", int(Placement::BELOW) }, { StyleIdx::pedalPosAbove, "pedalPosAbove", Spatium(-4) }, { StyleIdx::pedalPosBelow, "pedalPosBelow", Spatium(4) }, { StyleIdx::pedalLineWidth, "pedalLineWidth", Spatium(.15) }, @@ -182,11 +182,11 @@ static const StyleType styleTypes[] { { StyleIdx::pedalBeginTextOffset, "pedalBeginTextOffset", QPointF(0.0, 0.15) }, { StyleIdx::pedalHookHeight, "pedalHookHeight", Spatium(-1.2) }, - { StyleIdx::trillPlacement, "trillPlacement", int(Element::Placement::ABOVE) }, + { StyleIdx::trillPlacement, "trillPlacement", int(Placement::ABOVE) }, { StyleIdx::trillPosAbove, "trillPosAbove", Spatium(-1) }, { StyleIdx::trillPosBelow, "trillPosBelow", Spatium(1) }, - { StyleIdx::vibratoPlacement, "vibratoPlacement", int(Element::Placement::ABOVE) }, + { StyleIdx::vibratoPlacement, "vibratoPlacement", int(Placement::ABOVE) }, { StyleIdx::vibratoPosAbove, "vibratoPosAbove", Spatium(-1) }, { StyleIdx::vibratoPosBelow, "vibratoPosBelow", Spatium(1) }, @@ -286,7 +286,7 @@ static const StyleType styleTypes[] { { StyleIdx::voltaLineWidth, "voltaLineWidth", Spatium(.1) }, { StyleIdx::voltaLineStyle, "voltaLineStyle", QVariant(int(Qt::SolidLine)) }, - { StyleIdx::ottavaPlacement, "ottavaPlacement", int(Element::Placement::ABOVE) }, + { StyleIdx::ottavaPlacement, "ottavaPlacement", int(Placement::ABOVE) }, { StyleIdx::ottavaPosAbove, "ottavaPosAbove", Spatium(-3.0) }, { StyleIdx::ottavaPosBelow, "ottavaPosBelow", Spatium(3.0) }, { StyleIdx::ottavaHook, "ottavaHook", Spatium(1.9) }, @@ -327,14 +327,14 @@ static const StyleType styleTypes[] { { StyleIdx::autoplaceHairpinDynamicsDistance, "autoplaceHairpinDynamicsDistance", Spatium(0.5) }, - { StyleIdx::dynamicsPlacement, "dynamicsPlacement", int(Element::Placement::BELOW) }, + { StyleIdx::dynamicsPlacement, "dynamicsPlacement", int(Placement::BELOW) }, { StyleIdx::dynamicsPosAbove, "dynamicsPosAbove", Spatium(-2.0) }, { StyleIdx::dynamicsPosBelow, "dynamicsPosBelow", Spatium(1.0) }, { StyleIdx::dynamicsMinDistance, "dynamicsMinDistance", Spatium(0.5) }, { StyleIdx::autoplaceVerticalAlignRange, "autoplaceVerticalAlignRange", int(VerticalAlignRange::SYSTEM) }, - { StyleIdx::textLinePlacement, "textLinePlacement", int(Element::Placement::ABOVE) }, + { StyleIdx::textLinePlacement, "textLinePlacement", int(Placement::ABOVE) }, { StyleIdx::textLinePosAbove, "textLinePosAbove", Spatium(-3.5) }, { StyleIdx::textLinePosBelow, "textLinePosBelow", Spatium(3.5) }, @@ -525,7 +525,7 @@ static const StyleType styleTypes[] { { StyleIdx::tempoAlign, "tempoAlign", QVariant::fromValue(Align::LEFT | Align::BASELINE) }, { StyleIdx::tempoOffset, "tempoOffset", QPointF(0.0, -4.0) }, { StyleIdx::tempoSystemFlag, "tempoSystemFlag", true }, - { StyleIdx::tempoPlacement, "tempoPlacement", int(Element::Placement::ABOVE) }, + { StyleIdx::tempoPlacement, "tempoPlacement", int(Placement::ABOVE) }, { StyleIdx::tempoPosAbove, "tempoPosAbove", Spatium(-2.0) }, { StyleIdx::tempoPosBelow, "tempoPosBelow", Spatium(1.0) }, { StyleIdx::tempoMinDistance, "tempoMinDistance", Spatium(.5) }, @@ -595,7 +595,7 @@ static const StyleType styleTypes[] { { StyleIdx::rehearsalMarkFrameRound, "rehearsalMarkFrameRound", 20 }, { StyleIdx::rehearsalMarkFrameFgColor, "rehearsalMarkFrameFgColor", QColor(0, 0, 0, 255) }, { StyleIdx::rehearsalMarkFrameBgColor, "rehearsalMarkFrameBgColor", QColor(255, 255, 255, 0) }, - { StyleIdx::rehearsalMarkPlacement, "rehearsalMarkPlacement", int(Element::Placement::ABOVE) }, + { StyleIdx::rehearsalMarkPlacement, "rehearsalMarkPlacement", int(Placement::ABOVE) }, { StyleIdx::rehearsalMarkPosAbove, "rehearsalMarkPosAbove", Spatium(-3.0) }, { StyleIdx::rehearsalMarkPosBelow, "rehearsalMarkPosBelow", Spatium(2.0) }, { StyleIdx::rehearsalMarkMinDistance, "rehearsalMarkMinDistance", Spatium(0.5) }, @@ -713,7 +713,7 @@ static const StyleType styleTypes[] { { StyleIdx::letRingFontUnderline, "letRingFontUnderline", false }, { StyleIdx::letRingTextAlign, "letRingTextAlign", QVariant::fromValue(Align::LEFT | Align::VCENTER) }, { StyleIdx::letRingHookHeight, "letRingHookHeight", Spatium(0.6) }, - { StyleIdx::letRingPlacement, "letRingPlacement", int(Element::Placement::BELOW) }, + { StyleIdx::letRingPlacement, "letRingPlacement", int(Placement::BELOW) }, { StyleIdx::letRingPosAbove, "letRingPosAbove", Spatium(-4.0) }, { StyleIdx::letRingPosBelow, "letRingPosBelow", Spatium(4.0) }, { StyleIdx::letRingLineWidth, "letRingLineWidth", Spatium(0.15) }, @@ -728,7 +728,7 @@ static const StyleType styleTypes[] { { StyleIdx::palmMuteFontUnderline, "palmMuteFontUnderline", false }, { StyleIdx::palmMuteTextAlign, "palmMuteTextAlign", QVariant::fromValue(Align::LEFT | Align::VCENTER) }, { StyleIdx::palmMuteHookHeight, "palmMuteHookHeight", Spatium(0.6) }, - { StyleIdx::palmMutePlacement, "palmMutePlacement", int(Element::Placement::BELOW) }, + { StyleIdx::palmMutePlacement, "palmMutePlacement", int(Placement::BELOW) }, { StyleIdx::palmMutePosAbove, "palmMutePosAbove", Spatium(-4.0) }, { StyleIdx::palmMutePosBelow, "palmMutePosBelow", Spatium(4.0) }, { StyleIdx::palmMuteLineWidth, "palmMuteLineWidth", Spatium(0.15) }, diff --git a/libmscore/tempotext.cpp b/libmscore/tempotext.cpp index 302c874173797..1de347c3997ef 100644 --- a/libmscore/tempotext.cpp +++ b/libmscore/tempotext.cpp @@ -35,7 +35,7 @@ TempoText::TempoText(Score* s) _followText = false; _relative = 1.0; _isRelative = false; - setPlacement(Element::Placement::ABOVE); + setPlacement(Placement::ABOVE); } //--------------------------------------------------------- @@ -334,7 +334,7 @@ QVariant TempoText::propertyDefault(P_ID id) const case P_ID::TEMPO_FOLLOW_TEXT: return false; case P_ID::PLACEMENT: - return int(Element::Placement::ABOVE); + return int(Placement::ABOVE); default: return TextBase::propertyDefault(id); } diff --git a/libmscore/trill.cpp b/libmscore/trill.cpp index 103f91fddd944..6fccbd75014bc 100644 --- a/libmscore/trill.cpp +++ b/libmscore/trill.cpp @@ -296,7 +296,7 @@ Trill::Trill(Score* s) _accidental = 0; _ornamentStyle = MScore::OrnamentStyle::DEFAULT; setPlayArticulation(true); - setPlacement(Element::Placement::ABOVE); + setPlacement(Placement::ABOVE); } Trill::~Trill() @@ -548,7 +548,7 @@ QVariant Trill::propertyDefault(P_ID propertyId) const case P_ID::PLAY: return true; case P_ID::PLACEMENT: - return int(Element::Placement::ABOVE); + return int(Placement::ABOVE); default: return SLine::propertyDefault(propertyId); } diff --git a/libmscore/types.h b/libmscore/types.h index 02c5fda777cd3..845bed37a4677 100644 --- a/libmscore/types.h +++ b/libmscore/types.h @@ -51,6 +51,7 @@ enum class ElementType { REPEAT_MEASURE, TIE, ARTICULATION, + FERMATA, CHORDLINE, DYNAMIC, BEAM, @@ -155,6 +156,15 @@ enum class GlissandoStyle { CHROMATIC, WHITE_KEYS, BLACK_KEYS, DIATONIC }; +//--------------------------------------------------------- +// Placement +//--------------------------------------------------------- + +enum class Placement { + ABOVE, BELOW + }; + + Q_ENUM_NS(ElementType) Q_ENUM_NS(Direction) diff --git a/libmscore/vibrato.cpp b/libmscore/vibrato.cpp index 2637709af133e..4d27fc43cc9e2 100644 --- a/libmscore/vibrato.cpp +++ b/libmscore/vibrato.cpp @@ -212,7 +212,7 @@ Vibrato::Vibrato(Score* s) { _vibratoType = Type::GUITAR_VIBRATO; setPlayArticulation(true); - setPlacement(Element::Placement::ABOVE); + setPlacement(Placement::ABOVE); } Vibrato::~Vibrato() @@ -371,7 +371,7 @@ QVariant Vibrato::propertyDefault(P_ID propertyId) const case P_ID::PLAY: return true; case P_ID::PLACEMENT: - return int(Element::Placement::ABOVE); + return int(Placement::ABOVE); default: return SLine::propertyDefault(propertyId); } diff --git a/libmscore/xmlwriter.cpp b/libmscore/xmlwriter.cpp index 208c774d480ca..ce7f8ec8aabc5 100644 --- a/libmscore/xmlwriter.cpp +++ b/libmscore/xmlwriter.cpp @@ -248,11 +248,11 @@ void XmlWriter::tag(P_ID id, QVariant data, QVariant defaultData) } break; case P_TYPE::PLACEMENT: - switch (Element::Placement(data.toInt())) { - case Element::Placement::ABOVE: + switch (Placement(data.toInt())) { + case Placement::ABOVE: tag(name, QVariant("above")); break; - case Element::Placement::BELOW: + case Placement::BELOW: tag(name, QVariant("below")); break; } diff --git a/mscore/dragdrop.cpp b/mscore/dragdrop.cpp index cced327b293e3..95bc067b336da 100644 --- a/mscore/dragdrop.cpp +++ b/mscore/dragdrop.cpp @@ -335,6 +335,7 @@ void ScoreView::dragMoveEvent(QDragMoveEvent* event) case ElementType::GLISSANDO: case ElementType::BRACKET: case ElementType::ARTICULATION: + case ElementType::FERMATA: case ElementType::CHORDLINE: case ElementType::BEND: case ElementType::ACCIDENTAL: @@ -365,10 +366,6 @@ void ScoreView::dragMoveEvent(QDragMoveEvent* event) case ElementType::FRET_DIAGRAM: case ElementType::STAFFTYPE_CHANGE: { QList el = elementsAt(pos); -printf("elements at\n"); - for (Element* e : el) - printf(" %s\n", e->name()); - bool found = false; setDropTarget(0); for (const Element* e : el) { @@ -398,7 +395,6 @@ printf("elements at\n"); const QMimeData* md = event->mimeData(); if (md->hasUrls()) { -printf("===drag move urls\n"); QListul = md->urls(); QUrl u = ul.front(); if (u.scheme() == "file" || u.scheme() == "http") { @@ -541,6 +537,7 @@ void ScoreView::dropEvent(QDropEvent* event) case ElementType::GLISSANDO: case ElementType::BRACKET: case ElementType::ARTICULATION: + case ElementType::FERMATA: case ElementType::CHORDLINE: case ElementType::BEND: case ElementType::ACCIDENTAL: diff --git a/mscore/editlyrics.cpp b/mscore/editlyrics.cpp index ebed834392507..ff47ef4ddde25 100644 --- a/mscore/editlyrics.cpp +++ b/mscore/editlyrics.cpp @@ -85,9 +85,9 @@ void ScoreView::lyricsUpDown(bool up, bool end) int track = lyrics->track(); ChordRest* cr = lyrics->chordRest(); int verse = lyrics->no(); - Element::Placement placement = lyrics->placement(); + Placement placement = lyrics->placement(); - if (placement == Element::Placement::ABOVE) + if (placement == Placement::ABOVE) up = !up; if (up) { if (verse == 0) @@ -142,7 +142,7 @@ void ScoreView::lyricsTab(bool back, bool end, bool moveOnly) int track = lyrics->track(); Segment* segment = lyrics->segment(); int verse = lyrics->no(); - Element::Placement placement = lyrics->placement(); + Placement placement = lyrics->placement(); Segment* nextSegment = segment; if (back) { @@ -261,7 +261,7 @@ void ScoreView::lyricsMinus() int track = lyrics->track(); Segment* segment = lyrics->segment(); int verse = lyrics->no(); - Element::Placement placement = lyrics->placement(); + Placement placement = lyrics->placement(); changeState(ViewState::NORMAL); @@ -351,7 +351,7 @@ void ScoreView::lyricsUnderscore() int track = lyrics->track(); Segment* segment = lyrics->segment(); int verse = lyrics->no(); - Element::Placement placement = lyrics->placement(); + Placement placement = lyrics->placement(); int endTick = segment->tick(); // a previous melisma cannot extend beyond this point changeState(ViewState::NORMAL); @@ -521,7 +521,7 @@ void ScoreView::lyricsEndEdit() // of an existing melisma from a previous lyrics; in case, shorten it else { int verse = lyrics->no(); - Element::Placement placement = lyrics->placement(); + Placement placement = lyrics->placement(); int track = lyrics->track(); // search previous lyric diff --git a/mscore/editstyle.cpp b/mscore/editstyle.cpp index 1abffcfcf09da..1d9c8ab2a7611 100644 --- a/mscore/editstyle.cpp +++ b/mscore/editstyle.cpp @@ -351,8 +351,8 @@ EditStyle::EditStyle(Score* s, QWidget* parent) trillLinePlacement, vibratoLinePlacement, dynamicsPlacement, tempoTextPlacement, rehearsalMarkPlacement }) { cb->clear(); - cb->addItem(tr("Above"), int(Element::Placement::ABOVE)); - cb->addItem(tr("Below"), int(Element::Placement::BELOW)); + cb->addItem(tr("Above"), int(Placement::ABOVE)); + cb->addItem(tr("Below"), int(Placement::BELOW)); } autoplaceVerticalAlignRange->clear(); diff --git a/mscore/exportxml.cpp b/mscore/exportxml.cpp index 8b2e4f8fd4ff1..6ffc79d7b0fb3 100644 --- a/mscore/exportxml.cpp +++ b/mscore/exportxml.cpp @@ -2961,7 +2961,7 @@ static void directionTag(XmlWriter& xml, Attributes& attr, Element const* const } else if (el->isDynamic()) { tagname += " placement=\""; - tagname += el->placement() == Element::Placement::ABOVE + tagname += el->placement() == Placement::ABOVE ? "above" : "below"; tagname += "\""; } diff --git a/mscore/importmxmlpass2.cpp b/mscore/importmxmlpass2.cpp index 7e7e688f977ac..ca0c3d09926c0 100644 --- a/mscore/importmxmlpass2.cpp +++ b/mscore/importmxmlpass2.cpp @@ -85,7 +85,7 @@ namespace Ms { //--------------------------------------------------------- MusicXmlTupletDesc::MusicXmlTupletDesc() - : type(MxmlStartStop::NONE), placement(Element::Placement::BELOW), + : type(MxmlStartStop::NONE), placement(Placement::BELOW), bracket(Tuplet::BracketType::AUTO_BRACKET), shownumber(Tuplet::NumberType::SHOW_NUMBER) { // nothing @@ -908,7 +908,7 @@ static void addElemOffset(Element* el, int track, const QString& placement, Meas } else { el->setPlacement(placement == "above" - ? Element::Placement::ABOVE : Element::Placement::BELOW); + ? Placement::ABOVE : Placement::BELOW); } el->setTrack(track); @@ -1444,7 +1444,7 @@ static void setSLinePlacement(SLine* sli, const QString placement) } else { sli->setPlacement(placement == "above" - ? Element::Placement::ABOVE : Element::Placement::BELOW); + ? Placement::ABOVE : Placement::BELOW); } } @@ -2531,7 +2531,7 @@ void MusicXMLParserDirection::direction(const QString& partId, _rehearsalText = "" + _rehearsalText; // explicitly turn bold off t->setXmlText(_rehearsalText); if (!_hasDefaultY) - t->setPlacement(Element::Placement::ABOVE); // crude way to force placement TODO improve ? + t->setPlacement(Placement::ABOVE); // crude way to force placement TODO improve ? } } diff --git a/mscore/importmxmlpass2.h b/mscore/importmxmlpass2.h index 57d156ec3cb17..582355afb60de 100644 --- a/mscore/importmxmlpass2.h +++ b/mscore/importmxmlpass2.h @@ -56,7 +56,7 @@ enum class MxmlStartStop : char { struct MusicXmlTupletDesc { MusicXmlTupletDesc(); MxmlStartStop type; - Element::Placement placement; + Placement placement; Tuplet::BracketType bracket; Tuplet::NumberType shownumber; }; diff --git a/mscore/menus.cpp b/mscore/menus.cpp index 6f56f6cac752e..55caa1b8d762f 100644 --- a/mscore/menus.cpp +++ b/mscore/menus.cpp @@ -83,6 +83,7 @@ #include "libmscore/letring.h" #include "libmscore/vibrato.h" #include "libmscore/palmmute.h" +#include "libmscore/fermata.h" namespace Ms { @@ -641,8 +642,10 @@ Palette* MuseScore::newArticulationsPalette(PaletteType t) switch (t) { case PaletteType::BASIC: { + Fermata* f = new Fermata(SymId::fermataAbove, gscore); + sp->append(f, f->userName()); + static const std::vector art { - SymId::fermataAbove, SymId::articAccentAbove, SymId::articStaccatoAbove, SymId::articTenutoAbove, @@ -662,7 +665,7 @@ Palette* MuseScore::newArticulationsPalette(PaletteType t) case PaletteType::MASTER: case PaletteType::ADVANCED: { // do not include additional symbol-based fingerings (temporarily?) implemented as articulations - static const std::vector art { + static const std::vector fermatas { SymId::fermataAbove, SymId::fermataShortAbove, SymId::fermataLongAbove, @@ -670,7 +673,12 @@ Palette* MuseScore::newArticulationsPalette(PaletteType t) SymId::fermataShortHenzeAbove, SymId::fermataVeryLongAbove, SymId::fermataVeryShortAbove, - + }; + for (auto i : fermatas) { + Fermata* f = new Fermata(i, gscore); + sp->append(f, f->userName()); + } + static const std::vector art { SymId::articAccentAbove, SymId::articStaccatoAbove, SymId::articStaccatissimoAbove, @@ -1174,7 +1182,7 @@ Palette* MuseScore::newLinesPalette(PaletteType t) ottava = new Ottava(gscore); ottava->setOttavaType(OttavaType::OTTAVA_8VB); ottava->setLen(w); - ottava->setPlacement(Element::Placement::BELOW); + ottava->setPlacement(Placement::BELOW); sp->append(ottava, QT_TRANSLATE_NOOP("Palette", "8vb")); if (t != PaletteType::BASIC) { @@ -1186,7 +1194,7 @@ Palette* MuseScore::newLinesPalette(PaletteType t) ottava = new Ottava(gscore); ottava->setOttavaType(OttavaType::OTTAVA_15MB); ottava->setLen(w); - ottava->setPlacement(Element::Placement::BELOW); + ottava->setPlacement(Placement::BELOW); sp->append(ottava, QT_TRANSLATE_NOOP("Palette", "15mb")); ottava = new Ottava(gscore); @@ -1407,7 +1415,7 @@ Palette* MuseScore::newTextPalette() st = new StaffText(SubStyle::EXPRESSION, gscore); st->setXmlText(tr("Expression")); - st->setPlacement(Element::Placement::BELOW); + st->setPlacement(Placement::BELOW); sp->append(st, tr("Expression text")); InstrumentChange* is = new InstrumentChange(gscore); diff --git a/mscore/palette.cpp b/mscore/palette.cpp index 1f2117c2c82f1..3c7098c864865 100644 --- a/mscore/palette.cpp +++ b/mscore/palette.cpp @@ -651,14 +651,14 @@ void Palette::applyPaletteElement(PaletteCell* cell) Element* e = s->element(track); if (e == 0 || !score->selectionFilter().canSelect(e) || !score->selectionFilter().canSelectVoice(track)) continue; - if (e->type() == ElementType::CHORD) { - Chord* chord = static_cast(e); + if (e->isChord()) { + Chord* chord = toChord(e); for (Note* n : chord->notes()) applyDrop(score, viewer, n, element); } else { // do not apply articulation to barline in a range selection - if(e->type() != ElementType::BAR_LINE || element->type() != ElementType::ARTICULATION) + if (!e->isBarLine() || !element->isArticulation()) applyDrop(score, viewer, e, element); } } diff --git a/mscore/scoreview.cpp b/mscore/scoreview.cpp index 0a2d1a62e38ea..1ef01214c0e6d 100644 --- a/mscore/scoreview.cpp +++ b/mscore/scoreview.cpp @@ -3476,45 +3476,6 @@ void ScoreView::changeVoice(int voice) } } -//--------------------------------------------------------- -// modifyElement -//--------------------------------------------------------- - -void ScoreView::modifyElement(Element* el) - { - if (el == 0) { - qDebug("modifyElement: el==0"); - return; - } - Score* cs = el->score(); - if (!cs->selection().isSingle()) { - qDebug("modifyElement: cs->selection().state() != SelState::SINGLE"); - delete el; - return; - } - Element* e = cs->selection().element(); - Chord* chord; - if (e->type() == ElementType::CHORD) - chord = static_cast(e); - else if (e->type() == ElementType::NOTE) - chord = static_cast(e)->chord(); - else { - qDebug("modifyElement: no note/Chord selected:"); - e->dump(); - delete el; - return; - } - switch (el->type()) { - case ElementType::ARTICULATION: - chord->add(static_cast(el)); - break; - default: - qDebug("modifyElement: %s not ARTICULATION", el->name()); - delete el; - return; - } - } - //--------------------------------------------------------- // cmdTuplet //--------------------------------------------------------- @@ -3797,7 +3758,7 @@ void ScoreView::cmdAddText(TEXT type) s = new StaffText(_score); s->setTrack(cr->track()); s->initSubStyle(SubStyle::EXPRESSION); - s->setPlacement(Element::Placement::BELOW); + s->setPlacement(Placement::BELOW); s->setParent(cr->segment()); } break; diff --git a/mscore/scoreview.h b/mscore/scoreview.h index 1fed7aad6eb95..f3b1a2072357f 100644 --- a/mscore/scoreview.h +++ b/mscore/scoreview.h @@ -307,7 +307,6 @@ class ScoreView : public QWidget, public MuseScoreView { void setForeground(const QColor&); Page* addPage(); - void modifyElement(Element* obj); virtual void setScore(Score* s); virtual void removeScore() { _score = 0; } diff --git a/mtest/libmscore/compat206/articulations-ref.mscx b/mtest/libmscore/compat206/articulations-ref.mscx index 05c0ca8b54e18..435ff6dcfe483 100644 --- a/mtest/libmscore/compat206/articulations-ref.mscx +++ b/mtest/libmscore/compat206/articulations-ref.mscx @@ -92,43 +92,41 @@ 4 4 + + fermataAbove + quarter - - fermataAbove - 72 14 + + fermataAbove + quarter - - fermataAbove - 60 14 + + fermataAbove + quarter - - up - fermataAbove - 72 14 + + fermataAbove + quarter - - down - fermataBelow - 60 14 @@ -136,43 +134,41 @@ + + fermataShortAbove + quarter - - fermataShortAbove - 72 14 + + fermataShortAbove + quarter - - fermataShortAbove - 60 14 + + fermataShortAbove + quarter - - up - fermataShortAbove - 72 14 + + fermataShortAbove + quarter - - down - fermataShortBelow - 60 14 @@ -180,43 +176,41 @@ + + fermataLongAbove + quarter - - fermataLongAbove - 72 14 + + fermataLongAbove + quarter - - fermataLongAbove - 60 14 + + fermataLongAbove + quarter - - up - fermataLongAbove - 72 14 + + fermataLongAbove + quarter - - down - fermataLongBelow - 60 14 @@ -227,43 +221,41 @@ line + + fermataVeryLongAbove + quarter - - fermataVeryLongAbove - 72 14 + + fermataVeryLongAbove + quarter - - fermataVeryLongAbove - 60 14 + + fermataVeryLongAbove + quarter - - up - fermataVeryLongAbove - 72 14 + + fermataVeryLongAbove + quarter - - down - fermataVeryLongBelow - 60 14 diff --git a/mtest/libmscore/dynamic/tst_dynamic.cpp b/mtest/libmscore/dynamic/tst_dynamic.cpp index bc10f635260c5..188c142b04285 100644 --- a/mtest/libmscore/dynamic/tst_dynamic.cpp +++ b/mtest/libmscore/dynamic/tst_dynamic.cpp @@ -51,24 +51,24 @@ void TestDynamic::test1() Dynamic* dynamic = new Dynamic(score); dynamic->setDynamicType(Dynamic::Type(1)); - dynamic->setPlacement(Element::Placement::ABOVE); + dynamic->setPlacement(Placement::ABOVE); Dynamic* d = static_cast(writeReadElement(dynamic)); - QCOMPARE(d->placement(), Element::Placement::ABOVE); + QCOMPARE(d->placement(), Placement::ABOVE); delete d; - dynamic->setPlacement(Element::Placement::BELOW); + dynamic->setPlacement(Placement::BELOW); d = static_cast(writeReadElement(dynamic)); - QCOMPARE(d->placement(), Element::Placement::BELOW); + QCOMPARE(d->placement(), Placement::BELOW); delete d; - dynamic->setProperty(P_ID::PLACEMENT, int(Element::Placement::ABOVE)); + dynamic->setProperty(P_ID::PLACEMENT, int(Placement::ABOVE)); d = static_cast(writeReadElement(dynamic)); - QCOMPARE(d->placement(), Element::Placement::ABOVE); + QCOMPARE(d->placement(), Placement::ABOVE); delete d; - dynamic->setProperty(P_ID::PLACEMENT, int(Element::Placement::BELOW)); + dynamic->setProperty(P_ID::PLACEMENT, int(Placement::BELOW)); d = static_cast(writeReadElement(dynamic)); - QCOMPARE(d->placement(), Element::Placement::BELOW); + QCOMPARE(d->placement(), Placement::BELOW); delete d; dynamic->setVelocity(23); diff --git a/mtest/scripting/p1.log.ref b/mtest/scripting/p1.log.ref index 23804573fe6bb..016890974e167 100644 --- a/mtest/scripting/p1.log.ref +++ b/mtest/scripting/p1.log.ref @@ -2,14 +2,14 @@ test script p1: read score elements found:Clef (19) at 0 found:KeySig (20) at 0 found:TimeSig (22) at 0 -found:Chord (90) at 0 +found:Chord (91) at 0 durationType: beamMode:0 small:false stemDirection:AUTO duration: found:Rest (23) at 480 -found:Chord (90) at 960 +found:Chord (91) at 960 durationType: beamMode:0 small:false