diff --git a/src/libs/core/music/trhythm.h b/src/libs/core/music/trhythm.h index 84de937d862aaf81892508320498af237ae6cde9..d2436f0c8560b6b40b357a0a58b67cd8af8c859b 100644 --- a/src/libs/core/music/trhythm.h +++ b/src/libs/core/music/trhythm.h @@ -88,6 +88,7 @@ public: enum Ebeam : quint8 { e_noBeam = 0, e_beamStart = 16, e_beamCont = 32, e_beamEnd = 48 }; + Q_ENUM(Ebeam) enum Etie : quint8 { e_noTie = 0, e_tieStart = 64, e_tieCont = 128, e_tieEnd = 192 diff --git a/src/libs/core/score/tnoteobject.cpp b/src/libs/core/score/tnoteobject.cpp index c800600bb15ac4ccb80b3c94cb6d733d83c75958..041b0d0636e235ff6141f51b6342d919f6fd8a59 100644 --- a/src/libs/core/score/tnoteobject.cpp +++ b/src/libs/core/score/tnoteobject.cpp @@ -20,6 +20,7 @@ #include "tscoreobject.h" #include "tstaffobject.h" #include "tmeasureobject.h" +#include "tbeamobject.h" #include "tnotepair.h" #include "music/tnote.h" @@ -60,10 +61,10 @@ const qreal rtmGapArray[5][3] = { -TnoteObject::TnoteObject(TstaffObject* staffObj) : +TnoteObject::TnoteObject(TstaffObject* staffObj, TnotePair* wrapper) : QQuickItem(staffObj->staffItem()), m_staff(staffObj), - m_index(-1), + m_wrapper(wrapper), m_stemHeight(6.0) { setParent(m_staff->score()); // to avoid deleting with parent staff @@ -115,10 +116,17 @@ TnoteObject::~TnoteObject() { } +int TnoteObject::index() const { + return m_wrapper->index(); +} + + void TnoteObject::setStaff(TstaffObject* staffObj) { if (staffObj != m_staff) { m_staff = staffObj; setParentItem(m_staff->staffItem()); + if (m_wrapper->beam() && m_wrapper->beam()->last()->item() == this) + m_wrapper->beam()->changeStaff(m_staff); } else qDebug() << debug() << "has staff set already"; } @@ -129,6 +137,11 @@ void TnoteObject::setMeasure(TmeasureObject* m) { } +void TnoteObject::setStemHeight(qreal sh) { + m_stem->setHeight(sh); +} + + void TnoteObject::setColor(const QColor& c) { m_head->setProperty("color", c); m_alter->setProperty("color", c); @@ -159,7 +172,8 @@ void TnoteObject::setColor(const QColor& c) { */ void TnoteObject::setNote(const Tnote& n) { bool updateHead = n.rhythm() != m_note->rhythm() || n.isRest() != m_note->isRest() || n.hasDot() != m_note->hasDot(); - bool updateStem = updateHead || (n.rtm.beam() != Trhythm::e_noBeam) != (m_note->rtm.beam() != Trhythm::e_noBeam); + bool updateStem = updateHead || ((n.rtm.beam() != Trhythm::e_noBeam) != (m_note->rtm.beam() != Trhythm::e_noBeam)) + || (n.rtm.stemDown() != m_note->rtm.stemDown()); bool updateTie = n.rtm.tie() != m_note->rtm.tie(); *m_note = n; @@ -186,22 +200,8 @@ void TnoteObject::setNote(const Tnote& n) { updateStem = true; } - if (updateStem) { - if (m_notePosY && !m_note->isRest() && m_note->rhythm() > Trhythm::Whole ) { - if (m_note->rtm.beam() == Trhythm::e_noBeam) { - m_note->rtm.setStemDown(m_notePosY < staff()->upperLine() + 4.0); - m_stem->setHeight(qMax(6.0, qAbs(m_notePosY - (staff()->upperLine() + 4.0)))); - QString flag = getFlagText(); - m_flag->setProperty("text", flag); - if (!flag.isEmpty()) - m_flag->setY((m_note->rtm.stemDown() ? m_stem->height() : 0.0) - 15.0); - } - m_stem->setX(m_head->x() + (m_note->rtm.stemDown() ? 0.0 : 2.0)); - m_stem->setY(m_notePosY + (m_note->rtm.stemDown() ? 0.0 : - m_stem->height())); - m_stem->setVisible(true); - } else - m_stem->setVisible(false); - } + if (updateStem) + checkStem(); updateAlter(); updateWidth(); @@ -221,6 +221,8 @@ void TnoteObject::setNote(const Tnote& n) { void TnoteObject::setX(qreal xx) { updateTieScale(); QQuickItem::setX(xx + (m_accidText.isEmpty() ? 0.0 : m_alter->width())); + if (m_wrapper->beam() && m_wrapper->beam()->last()->item() == this) + m_wrapper->beam()->last()->beam()->drawBeam(); } @@ -262,7 +264,12 @@ void TnoteObject::checkTie() { qreal TnoteObject::tieWidth() { - return staff()->gapFactor() * rhythmFactor() + (this == m_measure->last()->object() ? 1.5 : 0.0) + (m_note->rtm.stemDown() ? 0.0 : m_flag->width() - 0.2); + return staff()->gapFactor() * rhythmFactor() + (this == m_measure->last()->item() ? 1.5 : 0.0) + (m_note->rtm.stemDown() ? 0.0 : m_flag->width() - 0.2); +} + + +QPointF TnoteObject::stemTop() { + return mapToItem(parentItem(), QPointF(m_stem->x(), m_stem->y() + (m_note->rtm.stemDown() ? m_stem->height() : 0.0))); } //################################################################################################# @@ -289,7 +296,7 @@ QString TnoteObject::getAccidText() { } } int id = index() - 1; // check the previous notes for accidentals - while (id >= 0 && m_staff->score()->noteSegment(id)->object()->measure() == measure()) { + while (id >= 0 && m_staff->score()->noteSegment(id)->item()->measure() == measure()) { if (m_staff->score()->noteSegment(id)->note()->note == m_note->note) { char prevAlter = m_staff->score()->noteSegment(id)->note()->alter; if (prevAlter != 0 && m_note->alter == 0) { @@ -401,3 +408,24 @@ void TnoteObject::updateTieScale() { m_tie->setProperty("stemDown", m_note->rtm.stemDown()); } } + + +void TnoteObject::checkStem() { + if (m_notePosY && !m_note->isRest() && m_note->rhythm() > Trhythm::Whole ) { + if (m_note->rtm.beam() == Trhythm::e_noBeam) { + m_note->rtm.setStemDown(m_notePosY < staff()->upperLine() + 4.0); + m_stem->setHeight(qMax(6.0, qAbs(m_notePosY - (staff()->upperLine() + 4.0)))); + QString flag = getFlagText(); + m_flag->setProperty("text", flag); + if (!flag.isEmpty()) + m_flag->setY((m_note->rtm.stemDown() ? m_stem->height() : 0.0) - 15.0); + } else { + if (m_flag->width() > 0.0) + m_flag->setProperty("text", QString()); + } + m_stem->setX(m_head->x() + (m_note->rtm.stemDown() ? 0.0 : 2.0)); + m_stem->setY(m_notePosY + (m_note->rtm.stemDown() ? 0.0 : - m_stem->height())); + m_stem->setVisible(true); + } else + m_stem->setVisible(false); +} diff --git a/src/libs/core/score/tnoteobject.h b/src/libs/core/score/tnoteobject.h index d4c92b7d0b9f8a008a8d2e92a6a9dc8700285c27..11de61a7b5665f22ce0c6aeeb859f628bf413f0a 100644 --- a/src/libs/core/score/tnoteobject.h +++ b/src/libs/core/score/tnoteobject.h @@ -26,6 +26,7 @@ class TstaffObject; class TmeasureObject; +class TnotePair; class Tnote; @@ -44,9 +45,10 @@ class NOOTKACORE_EXPORT TnoteObject : public QQuickItem friend class TscoreObject; friend class TstaffObject; friend class TmeasureObject; + friend class TbeamObject; public: - explicit TnoteObject(TstaffObject* staffObj = nullptr); + explicit TnoteObject(TstaffObject* staffObj = nullptr, TnotePair* wrapper = nullptr); ~TnoteObject(); TstaffObject* staff() const { return m_staff; } @@ -64,8 +66,7 @@ public: /** * Note number in the staff */ - int index() const { return m_index; } - void setIndex(int id) { m_index = id; } + int index() const; qreal stemHeight() const { return m_stemHeight; } void setStemHeight(qreal sh); @@ -75,7 +76,8 @@ public: void setColor(const QColor& c); /** - * Overrides standard @p setX() method to shift note segment about accidental symbol width (if it is set) + * Overrides standard @p setX() method to shift note segment about accidental symbol width (if it is set). + * It also updates tie (if any) and beam (for the last note in a beam group) */ void setX(qreal xx); @@ -89,6 +91,11 @@ public: */ qreal rhythmFactor(); + /** + * Returns position of the top of this note stem in staff coordinates + */ + QPointF stemTop(); + /** * Prints to std out debug info about this note: [NOTE number] in color */ @@ -124,9 +131,9 @@ protected: private: TstaffObject *m_staff; + TnotePair *m_wrapper; TmeasureObject *m_measure; Tnote *m_note; - int m_index; qreal m_notePosY; qreal m_x; QQuickItem *m_head, *m_alter, *m_stem, *m_flag, *m_bg; @@ -141,6 +148,7 @@ private: void updateWidth(); void updateNoteHead(); void updateTieScale(); + void checkStem(); }; #endif // TNOTEOBJECT_H